| OLD | NEW |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include "core/fpdfdoc/doc_vt.h" |
| 8 | |
| 9 #include "core/fpdfdoc/cpvt_wordinfo.h" | |
| 10 #include "core/fpdfdoc/csection.h" | |
| 11 #include "core/fpdfdoc/include/cpdf_variabletext.h" | |
| 12 #include "core/fpdfdoc/include/fpdf_doc.h" | |
| 13 #include "core/fpdfdoc/pdf_vt.h" | |
| 14 | 8 |
| 15 CLine::CLine() {} | 9 CLine::CLine() {} |
| 10 |
| 16 CLine::~CLine() {} | 11 CLine::~CLine() {} |
| 12 |
| 17 CPVT_WordPlace CLine::GetBeginWordPlace() const { | 13 CPVT_WordPlace CLine::GetBeginWordPlace() const { |
| 18 return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, -1); | 14 return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, -1); |
| 19 } | 15 } |
| 20 CPVT_WordPlace CLine::GetEndWordPlace() const { | 16 CPVT_WordPlace CLine::GetEndWordPlace() const { |
| 21 return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, | 17 return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, |
| 22 m_LineInfo.nEndWordIndex); | 18 m_LineInfo.nEndWordIndex); |
| 23 } | 19 } |
| 24 CPVT_WordPlace CLine::GetPrevWordPlace(const CPVT_WordPlace& place) const { | 20 CPVT_WordPlace CLine::GetPrevWordPlace(const CPVT_WordPlace& place) const { |
| 25 if (place.nWordIndex > m_LineInfo.nEndWordIndex) { | 21 if (place.nWordIndex > m_LineInfo.nEndWordIndex) { |
| 26 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, | 22 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, |
| 27 m_LineInfo.nEndWordIndex); | 23 m_LineInfo.nEndWordIndex); |
| 28 } | 24 } |
| 29 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, | 25 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, |
| 30 place.nWordIndex - 1); | 26 place.nWordIndex - 1); |
| 31 } | 27 } |
| 32 CPVT_WordPlace CLine::GetNextWordPlace(const CPVT_WordPlace& place) const { | 28 CPVT_WordPlace CLine::GetNextWordPlace(const CPVT_WordPlace& place) const { |
| 33 if (place.nWordIndex < m_LineInfo.nBeginWordIndex) { | 29 if (place.nWordIndex < m_LineInfo.nBeginWordIndex) { |
| 34 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, | 30 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, |
| 35 m_LineInfo.nBeginWordIndex); | 31 m_LineInfo.nBeginWordIndex); |
| 36 } | 32 } |
| 37 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, | 33 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, |
| 38 place.nWordIndex + 1); | 34 place.nWordIndex + 1); |
| 39 } | 35 } |
| 40 CSection::CSection(CPDF_VariableText* pVT) : m_pVT(pVT) {} | 36 |
| 41 CSection::~CSection() { | 37 CPDF_EditContainer::CPDF_EditContainer() |
| 42 ResetAll(); | 38 : m_rcPlate(0, 0, 0, 0), m_rcContent(0, 0, 0, 0) {} |
| 39 |
| 40 CPDF_EditContainer::~CPDF_EditContainer() {} |
| 41 |
| 42 CFX_FloatRect CPDF_EditContainer::InToOut(const CPVT_FloatRect& rect) const { |
| 43 CFX_FloatPoint ptLeftTop = InToOut(CFX_FloatPoint(rect.left, rect.top)); |
| 44 CFX_FloatPoint ptRightBottom = |
| 45 InToOut(CFX_FloatPoint(rect.right, rect.bottom)); |
| 46 return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x, |
| 47 ptLeftTop.y); |
| 43 } | 48 } |
| 44 void CSection::ResetAll() { | |
| 45 ResetWordArray(); | |
| 46 ResetLineArray(); | |
| 47 } | |
| 48 void CSection::ResetLineArray() { | |
| 49 m_LineArray.RemoveAll(); | |
| 50 } | |
| 51 void CSection::ResetWordArray() { | |
| 52 for (int32_t i = 0, sz = m_WordArray.GetSize(); i < sz; i++) { | |
| 53 delete m_WordArray.GetAt(i); | |
| 54 } | |
| 55 m_WordArray.RemoveAll(); | |
| 56 } | |
| 57 void CSection::ResetLinePlace() { | |
| 58 for (int32_t i = 0, sz = m_LineArray.GetSize(); i < sz; i++) { | |
| 59 if (CLine* pLine = m_LineArray.GetAt(i)) { | |
| 60 pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1); | |
| 61 } | |
| 62 } | |
| 63 } | |
| 64 CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace& place, | |
| 65 const CPVT_WordInfo& wordinfo) { | |
| 66 CPVT_WordInfo* pWord = new CPVT_WordInfo(wordinfo); | |
| 67 int32_t nWordIndex = | |
| 68 std::max(std::min(place.nWordIndex, m_WordArray.GetSize()), 0); | |
| 69 if (nWordIndex == m_WordArray.GetSize()) { | |
| 70 m_WordArray.Add(pWord); | |
| 71 } else { | |
| 72 m_WordArray.InsertAt(nWordIndex, pWord); | |
| 73 } | |
| 74 return place; | |
| 75 } | |
| 76 CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo& lineinfo) { | |
| 77 return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.Add(lineinfo), -1); | |
| 78 } | |
| 79 CPVT_FloatRect CSection::Rearrange() { | |
| 80 if (m_pVT->m_nCharArray > 0) { | |
| 81 return CTypeset(this).CharArray(); | |
| 82 } | |
| 83 return CTypeset(this).Typeset(); | |
| 84 } | |
| 85 CPVT_Size CSection::GetSectionSize(FX_FLOAT fFontSize) { | |
| 86 return CTypeset(this).GetEditSize(fFontSize); | |
| 87 } | |
| 88 CPVT_WordPlace CSection::GetBeginWordPlace() const { | |
| 89 if (CLine* pLine = m_LineArray.GetAt(0)) { | |
| 90 return pLine->GetBeginWordPlace(); | |
| 91 } | |
| 92 return SecPlace; | |
| 93 } | |
| 94 CPVT_WordPlace CSection::GetEndWordPlace() const { | |
| 95 if (CLine* pLine = m_LineArray.GetAt(m_LineArray.GetSize() - 1)) { | |
| 96 return pLine->GetEndWordPlace(); | |
| 97 } | |
| 98 return SecPlace; | |
| 99 } | |
| 100 CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace& place) const { | |
| 101 if (place.nLineIndex < 0) { | |
| 102 return GetBeginWordPlace(); | |
| 103 } | |
| 104 if (place.nLineIndex >= m_LineArray.GetSize()) { | |
| 105 return GetEndWordPlace(); | |
| 106 } | |
| 107 if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) { | |
| 108 if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) { | |
| 109 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1); | |
| 110 } | |
| 111 if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) { | |
| 112 if (CLine* pPrevLine = m_LineArray.GetAt(place.nLineIndex - 1)) { | |
| 113 return pPrevLine->GetEndWordPlace(); | |
| 114 } | |
| 115 } else { | |
| 116 return pLine->GetPrevWordPlace(place); | |
| 117 } | |
| 118 } | |
| 119 return place; | |
| 120 } | |
| 121 CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace& place) const { | |
| 122 if (place.nLineIndex < 0) { | |
| 123 return GetBeginWordPlace(); | |
| 124 } | |
| 125 if (place.nLineIndex >= m_LineArray.GetSize()) { | |
| 126 return GetEndWordPlace(); | |
| 127 } | |
| 128 if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) { | |
| 129 if (place.nWordIndex >= pLine->m_LineInfo.nEndWordIndex) { | |
| 130 if (CLine* pNextLine = m_LineArray.GetAt(place.nLineIndex + 1)) { | |
| 131 return pNextLine->GetBeginWordPlace(); | |
| 132 } | |
| 133 } else { | |
| 134 return pLine->GetNextWordPlace(place); | |
| 135 } | |
| 136 } | |
| 137 return place; | |
| 138 } | |
| 139 void CSection::UpdateWordPlace(CPVT_WordPlace& place) const { | |
| 140 int32_t nLeft = 0; | |
| 141 int32_t nRight = m_LineArray.GetSize() - 1; | |
| 142 int32_t nMid = (nLeft + nRight) / 2; | |
| 143 while (nLeft <= nRight) { | |
| 144 if (CLine* pLine = m_LineArray.GetAt(nMid)) { | |
| 145 if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) { | |
| 146 nRight = nMid - 1; | |
| 147 nMid = (nLeft + nRight) / 2; | |
| 148 } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) { | |
| 149 nLeft = nMid + 1; | |
| 150 nMid = (nLeft + nRight) / 2; | |
| 151 } else { | |
| 152 place.nLineIndex = nMid; | |
| 153 return; | |
| 154 } | |
| 155 } else { | |
| 156 break; | |
| 157 } | |
| 158 } | |
| 159 } | |
| 160 CPVT_WordPlace CSection::SearchWordPlace(const CFX_FloatPoint& point) const { | |
| 161 ASSERT(m_pVT); | |
| 162 CPVT_WordPlace place = GetBeginWordPlace(); | |
| 163 FX_BOOL bUp = TRUE; | |
| 164 FX_BOOL bDown = TRUE; | |
| 165 int32_t nLeft = 0; | |
| 166 int32_t nRight = m_LineArray.GetSize() - 1; | |
| 167 int32_t nMid = m_LineArray.GetSize() / 2; | |
| 168 FX_FLOAT fTop = 0; | |
| 169 FX_FLOAT fBottom = 0; | |
| 170 while (nLeft <= nRight) { | |
| 171 if (CLine* pLine = m_LineArray.GetAt(nMid)) { | |
| 172 fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent - | |
| 173 m_pVT->GetLineLeading(m_SecInfo); | |
| 174 fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent; | |
| 175 if (IsFloatBigger(point.y, fTop)) { | |
| 176 bUp = FALSE; | |
| 177 } | |
| 178 if (IsFloatSmaller(point.y, fBottom)) { | |
| 179 bDown = FALSE; | |
| 180 } | |
| 181 if (IsFloatSmaller(point.y, fTop)) { | |
| 182 nRight = nMid - 1; | |
| 183 nMid = (nLeft + nRight) / 2; | |
| 184 continue; | |
| 185 } else if (IsFloatBigger(point.y, fBottom)) { | |
| 186 nLeft = nMid + 1; | |
| 187 nMid = (nLeft + nRight) / 2; | |
| 188 continue; | |
| 189 } else { | |
| 190 place = SearchWordPlace( | |
| 191 point.x, | |
| 192 CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), | |
| 193 pLine->GetEndWordPlace())); | |
| 194 place.nLineIndex = nMid; | |
| 195 return place; | |
| 196 } | |
| 197 } | |
| 198 } | |
| 199 if (bUp) { | |
| 200 place = GetBeginWordPlace(); | |
| 201 } | |
| 202 if (bDown) { | |
| 203 place = GetEndWordPlace(); | |
| 204 } | |
| 205 return place; | |
| 206 } | |
| 207 CPVT_WordPlace CSection::SearchWordPlace( | |
| 208 FX_FLOAT fx, | |
| 209 const CPVT_WordPlace& lineplace) const { | |
| 210 if (CLine* pLine = m_LineArray.GetAt(lineplace.nLineIndex)) { | |
| 211 return SearchWordPlace( | |
| 212 fx - m_SecInfo.rcSection.left, | |
| 213 CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), | |
| 214 pLine->GetEndWordPlace())); | |
| 215 } | |
| 216 return GetBeginWordPlace(); | |
| 217 } | |
| 218 CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, | |
| 219 const CPVT_WordRange& range) const { | |
| 220 CPVT_WordPlace wordplace = range.BeginPos; | |
| 221 wordplace.nWordIndex = -1; | |
| 222 if (!m_pVT) { | |
| 223 return wordplace; | |
| 224 } | |
| 225 int32_t nLeft = range.BeginPos.nWordIndex; | |
| 226 int32_t nRight = range.EndPos.nWordIndex + 1; | |
| 227 int32_t nMid = (nLeft + nRight) / 2; | |
| 228 while (nLeft < nRight) { | |
| 229 if (nMid == nLeft) { | |
| 230 break; | |
| 231 } | |
| 232 if (nMid == nRight) { | |
| 233 nMid--; | |
| 234 break; | |
| 235 } | |
| 236 if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) { | |
| 237 if (fx > | |
| 238 pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) { | |
| 239 nLeft = nMid; | |
| 240 nMid = (nLeft + nRight) / 2; | |
| 241 continue; | |
| 242 } else { | |
| 243 nRight = nMid; | |
| 244 nMid = (nLeft + nRight) / 2; | |
| 245 continue; | |
| 246 } | |
| 247 } else { | |
| 248 break; | |
| 249 } | |
| 250 } | |
| 251 if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) { | |
| 252 if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) { | |
| 253 wordplace.nWordIndex = nMid; | |
| 254 } | |
| 255 } | |
| 256 return wordplace; | |
| 257 } | |
| 258 void CSection::ClearLeftWords(int32_t nWordIndex) { | |
| 259 for (int32_t i = nWordIndex; i >= 0; i--) { | |
| 260 delete m_WordArray.GetAt(i); | |
| 261 m_WordArray.RemoveAt(i); | |
| 262 } | |
| 263 } | |
| 264 void CSection::ClearRightWords(int32_t nWordIndex) { | |
| 265 for (int32_t i = m_WordArray.GetSize() - 1; i > nWordIndex; i--) { | |
| 266 delete m_WordArray.GetAt(i); | |
| 267 m_WordArray.RemoveAt(i); | |
| 268 } | |
| 269 } | |
| 270 void CSection::ClearMidWords(int32_t nBeginIndex, int32_t nEndIndex) { | |
| 271 for (int32_t i = nEndIndex; i > nBeginIndex; i--) { | |
| 272 delete m_WordArray.GetAt(i); | |
| 273 m_WordArray.RemoveAt(i); | |
| 274 } | |
| 275 } | |
| 276 void CSection::ClearWords(const CPVT_WordRange& PlaceRange) { | |
| 277 CPVT_WordPlace SecBeginPos = GetBeginWordPlace(); | |
| 278 CPVT_WordPlace SecEndPos = GetEndWordPlace(); | |
| 279 if (PlaceRange.BeginPos.WordCmp(SecBeginPos) >= 0) { | |
| 280 if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) { | |
| 281 ClearMidWords(PlaceRange.BeginPos.nWordIndex, | |
| 282 PlaceRange.EndPos.nWordIndex); | |
| 283 } else { | |
| 284 ClearRightWords(PlaceRange.BeginPos.nWordIndex); | |
| 285 } | |
| 286 } else if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) { | |
| 287 ClearLeftWords(PlaceRange.EndPos.nWordIndex); | |
| 288 } else { | |
| 289 ResetWordArray(); | |
| 290 } | |
| 291 } | |
| 292 void CSection::ClearWord(const CPVT_WordPlace& place) { | |
| 293 delete m_WordArray.GetAt(place.nWordIndex); | |
| 294 m_WordArray.RemoveAt(place.nWordIndex); | |
| 295 } | |
| 296 CTypeset::CTypeset(CSection* pSection) | |
| 297 : m_rcRet(0.0f, 0.0f, 0.0f, 0.0f), | |
| 298 m_pVT(pSection->m_pVT), | |
| 299 m_pSection(pSection) {} | |
| 300 CTypeset::~CTypeset() {} | |
| 301 CPVT_FloatRect CTypeset::CharArray() { | |
| 302 ASSERT(m_pSection); | |
| 303 FX_FLOAT fLineAscent = | |
| 304 m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize()); | |
| 305 FX_FLOAT fLineDescent = | |
| 306 m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize()); | |
| 307 m_rcRet.Default(); | |
| 308 FX_FLOAT x = 0.0f, y = 0.0f; | |
| 309 FX_FLOAT fNextWidth; | |
| 310 int32_t nStart = 0; | |
| 311 FX_FLOAT fNodeWidth = m_pVT->GetPlateWidth() / | |
| 312 (m_pVT->m_nCharArray <= 0 ? 1 : m_pVT->m_nCharArray); | |
| 313 if (CLine* pLine = m_pSection->m_LineArray.GetAt(0)) { | |
| 314 x = 0.0f; | |
| 315 y += m_pVT->GetLineLeading(m_pSection->m_SecInfo); | |
| 316 y += fLineAscent; | |
| 317 nStart = 0; | |
| 318 switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) { | |
| 319 case 0: | |
| 320 pLine->m_LineInfo.fLineX = fNodeWidth * VARIABLETEXT_HALF; | |
| 321 break; | |
| 322 case 1: | |
| 323 nStart = (m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize()) / 2; | |
| 324 pLine->m_LineInfo.fLineX = | |
| 325 fNodeWidth * nStart - fNodeWidth * VARIABLETEXT_HALF; | |
| 326 break; | |
| 327 case 2: | |
| 328 nStart = m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize(); | |
| 329 pLine->m_LineInfo.fLineX = | |
| 330 fNodeWidth * nStart - fNodeWidth * VARIABLETEXT_HALF; | |
| 331 break; | |
| 332 } | |
| 333 for (int32_t w = 0, sz = m_pSection->m_WordArray.GetSize(); w < sz; w++) { | |
| 334 if (w >= m_pVT->m_nCharArray) { | |
| 335 break; | |
| 336 } | |
| 337 fNextWidth = 0; | |
| 338 if (CPVT_WordInfo* pNextWord = | |
| 339 (CPVT_WordInfo*)m_pSection->m_WordArray.GetAt(w + 1)) { | |
| 340 pNextWord->fWordTail = 0; | |
| 341 fNextWidth = m_pVT->GetWordWidth(*pNextWord); | |
| 342 } | |
| 343 if (CPVT_WordInfo* pWord = | |
| 344 (CPVT_WordInfo*)m_pSection->m_WordArray.GetAt(w)) { | |
| 345 pWord->fWordTail = 0; | |
| 346 FX_FLOAT fWordWidth = m_pVT->GetWordWidth(*pWord); | |
| 347 FX_FLOAT fWordAscent = m_pVT->GetWordAscent(*pWord); | |
| 348 FX_FLOAT fWordDescent = m_pVT->GetWordDescent(*pWord); | |
| 349 x = (FX_FLOAT)(fNodeWidth * (w + nStart + 0.5) - | |
| 350 fWordWidth * VARIABLETEXT_HALF); | |
| 351 pWord->fWordX = x; | |
| 352 pWord->fWordY = y; | |
| 353 if (w == 0) { | |
| 354 pLine->m_LineInfo.fLineX = x; | |
| 355 } | |
| 356 if (w != m_pSection->m_WordArray.GetSize() - 1) { | |
| 357 pWord->fWordTail = | |
| 358 (fNodeWidth - (fWordWidth + fNextWidth) * VARIABLETEXT_HALF > 0 | |
| 359 ? fNodeWidth - (fWordWidth + fNextWidth) * VARIABLETEXT_HALF | |
| 360 : 0); | |
| 361 } else { | |
| 362 pWord->fWordTail = 0; | |
| 363 } | |
| 364 x += fWordWidth; | |
| 365 fLineAscent = std::max(fLineAscent, fWordAscent); | |
| 366 fLineDescent = std::min(fLineDescent, fWordDescent); | |
| 367 } | |
| 368 } | |
| 369 pLine->m_LineInfo.nBeginWordIndex = 0; | |
| 370 pLine->m_LineInfo.nEndWordIndex = m_pSection->m_WordArray.GetSize() - 1; | |
| 371 pLine->m_LineInfo.fLineY = y; | |
| 372 pLine->m_LineInfo.fLineWidth = x - pLine->m_LineInfo.fLineX; | |
| 373 pLine->m_LineInfo.fLineAscent = fLineAscent; | |
| 374 pLine->m_LineInfo.fLineDescent = fLineDescent; | |
| 375 y -= fLineDescent; | |
| 376 } | |
| 377 return m_rcRet = CPVT_FloatRect(0, 0, x, y); | |
| 378 } | |
| 379 CPVT_Size CTypeset::GetEditSize(FX_FLOAT fFontSize) { | |
| 380 ASSERT(m_pSection); | |
| 381 ASSERT(m_pVT); | |
| 382 SplitLines(FALSE, fFontSize); | |
| 383 return CPVT_Size(m_rcRet.Width(), m_rcRet.Height()); | |
| 384 } | |
| 385 CPVT_FloatRect CTypeset::Typeset() { | |
| 386 ASSERT(m_pVT); | |
| 387 m_pSection->m_LineArray.Empty(); | |
| 388 SplitLines(TRUE, 0.0f); | |
| 389 m_pSection->m_LineArray.Clear(); | |
| 390 OutputLines(); | |
| 391 return m_rcRet; | |
| 392 } | |
| 393 | |
| 394 static const uint8_t special_chars[128] = { | |
| 395 0x00, 0x0C, 0x08, 0x0C, 0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
| 397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, | |
| 398 0x10, 0x00, 0x00, 0x28, 0x0C, 0x08, 0x00, 0x00, 0x28, 0x28, 0x28, 0x28, | |
| 399 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x08, | |
| 400 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | |
| 401 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | |
| 402 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0C, 0x00, 0x08, 0x00, 0x00, | |
| 403 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | |
| 404 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | |
| 405 0x01, 0x01, 0x01, 0x0C, 0x00, 0x08, 0x00, 0x00, | |
| 406 }; | |
| 407 | |
| 408 static bool IsLatin(uint16_t word) { | |
| 409 if (word <= 0x007F) | |
| 410 return !!(special_chars[word] & 0x01); | |
| 411 | |
| 412 return ((word >= 0x00C0 && word <= 0x00FF) || | |
| 413 (word >= 0x0100 && word <= 0x024F) || | |
| 414 (word >= 0x1E00 && word <= 0x1EFF) || | |
| 415 (word >= 0x2C60 && word <= 0x2C7F) || | |
| 416 (word >= 0xA720 && word <= 0xA7FF) || | |
| 417 (word >= 0xFF21 && word <= 0xFF3A) || | |
| 418 (word >= 0xFF41 && word <= 0xFF5A)); | |
| 419 } | |
| 420 | |
| 421 static bool IsDigit(uint32_t word) { | |
| 422 return word >= 0x0030 && word <= 0x0039; | |
| 423 } | |
| 424 | |
| 425 static bool IsCJK(uint32_t word) { | |
| 426 if ((word >= 0x1100 && word <= 0x11FF) || | |
| 427 (word >= 0x2E80 && word <= 0x2FFF) || | |
| 428 (word >= 0x3040 && word <= 0x9FBF) || | |
| 429 (word >= 0xAC00 && word <= 0xD7AF) || | |
| 430 (word >= 0xF900 && word <= 0xFAFF) || | |
| 431 (word >= 0xFE30 && word <= 0xFE4F) || | |
| 432 (word >= 0x20000 && word <= 0x2A6DF) || | |
| 433 (word >= 0x2F800 && word <= 0x2FA1F)) { | |
| 434 return true; | |
| 435 } | |
| 436 if (word >= 0x3000 && word <= 0x303F) { | |
| 437 return ( | |
| 438 word == 0x3005 || word == 0x3006 || word == 0x3021 || word == 0x3022 || | |
| 439 word == 0x3023 || word == 0x3024 || word == 0x3025 || word == 0x3026 || | |
| 440 word == 0x3027 || word == 0x3028 || word == 0x3029 || word == 0x3031 || | |
| 441 word == 0x3032 || word == 0x3033 || word == 0x3034 || word == 0x3035); | |
| 442 } | |
| 443 return word >= 0xFF66 && word <= 0xFF9D; | |
| 444 } | |
| 445 | |
| 446 static bool IsPunctuation(uint32_t word) { | |
| 447 if (word <= 0x007F) | |
| 448 return !!(special_chars[word] & 0x08); | |
| 449 | |
| 450 if (word >= 0x0080 && word <= 0x00FF) { | |
| 451 return (word == 0x0082 || word == 0x0084 || word == 0x0085 || | |
| 452 word == 0x0091 || word == 0x0092 || word == 0x0093 || | |
| 453 word <= 0x0094 || word == 0x0096 || word == 0x00B4 || | |
| 454 word == 0x00B8); | |
| 455 } | |
| 456 | |
| 457 if (word >= 0x2000 && word <= 0x206F) { | |
| 458 return ( | |
| 459 word == 0x2010 || word == 0x2011 || word == 0x2012 || word == 0x2013 || | |
| 460 word == 0x2018 || word == 0x2019 || word == 0x201A || word == 0x201B || | |
| 461 word == 0x201C || word == 0x201D || word == 0x201E || word == 0x201F || | |
| 462 word == 0x2032 || word == 0x2033 || word == 0x2034 || word == 0x2035 || | |
| 463 word == 0x2036 || word == 0x2037 || word == 0x203C || word == 0x203D || | |
| 464 word == 0x203E || word == 0x2044); | |
| 465 } | |
| 466 | |
| 467 if (word >= 0x3000 && word <= 0x303F) { | |
| 468 return ( | |
| 469 word == 0x3001 || word == 0x3002 || word == 0x3003 || word == 0x3005 || | |
| 470 word == 0x3009 || word == 0x300A || word == 0x300B || word == 0x300C || | |
| 471 word == 0x300D || word == 0x300F || word == 0x300E || word == 0x3010 || | |
| 472 word == 0x3011 || word == 0x3014 || word == 0x3015 || word == 0x3016 || | |
| 473 word == 0x3017 || word == 0x3018 || word == 0x3019 || word == 0x301A || | |
| 474 word == 0x301B || word == 0x301D || word == 0x301E || word == 0x301F); | |
| 475 } | |
| 476 | |
| 477 if (word >= 0xFE50 && word <= 0xFE6F) | |
| 478 return (word >= 0xFE50 && word <= 0xFE5E) || word == 0xFE63; | |
| 479 | |
| 480 if (word >= 0xFF00 && word <= 0xFFEF) { | |
| 481 return ( | |
| 482 word == 0xFF01 || word == 0xFF02 || word == 0xFF07 || word == 0xFF08 || | |
| 483 word == 0xFF09 || word == 0xFF0C || word == 0xFF0E || word == 0xFF0F || | |
| 484 word == 0xFF1A || word == 0xFF1B || word == 0xFF1F || word == 0xFF3B || | |
| 485 word == 0xFF3D || word == 0xFF40 || word == 0xFF5B || word == 0xFF5C || | |
| 486 word == 0xFF5D || word == 0xFF61 || word == 0xFF62 || word == 0xFF63 || | |
| 487 word == 0xFF64 || word == 0xFF65 || word == 0xFF9E || word == 0xFF9F); | |
| 488 } | |
| 489 | |
| 490 return false; | |
| 491 } | |
| 492 | |
| 493 static bool IsConnectiveSymbol(uint32_t word) { | |
| 494 return word <= 0x007F && (special_chars[word] & 0x20); | |
| 495 } | |
| 496 | |
| 497 static bool IsOpenStylePunctuation(uint32_t word) { | |
| 498 if (word <= 0x007F) | |
| 499 return !!(special_chars[word] & 0x04); | |
| 500 | |
| 501 return (word == 0x300A || word == 0x300C || word == 0x300E || | |
| 502 word == 0x3010 || word == 0x3014 || word == 0x3016 || | |
| 503 word == 0x3018 || word == 0x301A || word == 0xFF08 || | |
| 504 word == 0xFF3B || word == 0xFF5B || word == 0xFF62); | |
| 505 } | |
| 506 | |
| 507 static bool IsCurrencySymbol(uint16_t word) { | |
| 508 return (word == 0x0024 || word == 0x0080 || word == 0x00A2 || | |
| 509 word == 0x00A3 || word == 0x00A4 || word == 0x00A5 || | |
| 510 (word >= 0x20A0 && word <= 0x20CF) || word == 0xFE69 || | |
| 511 word == 0xFF04 || word == 0xFFE0 || word == 0xFFE1 || | |
| 512 word == 0xFFE5 || word == 0xFFE6); | |
| 513 } | |
| 514 | |
| 515 static bool IsPrefixSymbol(uint16_t word) { | |
| 516 return IsCurrencySymbol(word) || word == 0x2116; | |
| 517 } | |
| 518 | |
| 519 static bool IsSpace(uint16_t word) { | |
| 520 return word == 0x0020 || word == 0x3000; | |
| 521 } | |
| 522 | |
| 523 static bool NeedDivision(uint16_t prevWord, uint16_t curWord) { | |
| 524 if ((IsLatin(prevWord) || IsDigit(prevWord)) && | |
| 525 (IsLatin(curWord) || IsDigit(curWord))) { | |
| 526 return false; | |
| 527 } | |
| 528 if (IsSpace(curWord) || IsPunctuation(curWord)) { | |
| 529 return false; | |
| 530 } | |
| 531 if (IsConnectiveSymbol(prevWord) || IsConnectiveSymbol(curWord)) { | |
| 532 return false; | |
| 533 } | |
| 534 if (IsSpace(prevWord) || IsPunctuation(prevWord)) { | |
| 535 return true; | |
| 536 } | |
| 537 if (IsPrefixSymbol(prevWord)) { | |
| 538 return false; | |
| 539 } | |
| 540 if (IsPrefixSymbol(curWord) || IsCJK(curWord)) { | |
| 541 return true; | |
| 542 } | |
| 543 if (IsCJK(prevWord)) { | |
| 544 return true; | |
| 545 } | |
| 546 return false; | |
| 547 } | |
| 548 | |
| 549 void CTypeset::SplitLines(FX_BOOL bTypeset, FX_FLOAT fFontSize) { | |
| 550 ASSERT(m_pVT); | |
| 551 ASSERT(m_pSection); | |
| 552 int32_t nLineHead = 0; | |
| 553 int32_t nLineTail = 0; | |
| 554 FX_FLOAT fMaxX = 0.0f, fMaxY = 0.0f; | |
| 555 FX_FLOAT fLineWidth = 0.0f, fBackupLineWidth = 0.0f; | |
| 556 FX_FLOAT fLineAscent = 0.0f, fBackupLineAscent = 0.0f; | |
| 557 FX_FLOAT fLineDescent = 0.0f, fBackupLineDescent = 0.0f; | |
| 558 int32_t nWordStartPos = 0; | |
| 559 FX_BOOL bFullWord = FALSE; | |
| 560 int32_t nLineFullWordIndex = 0; | |
| 561 int32_t nCharIndex = 0; | |
| 562 CPVT_LineInfo line; | |
| 563 FX_FLOAT fWordWidth = 0; | |
| 564 FX_FLOAT fTypesetWidth = std::max( | |
| 565 m_pVT->GetPlateWidth() - m_pVT->GetLineIndent(m_pSection->m_SecInfo), | |
| 566 0.0f); | |
| 567 int32_t nTotalWords = m_pSection->m_WordArray.GetSize(); | |
| 568 FX_BOOL bOpened = FALSE; | |
| 569 if (nTotalWords > 0) { | |
| 570 int32_t i = 0; | |
| 571 while (i < nTotalWords) { | |
| 572 CPVT_WordInfo* pWord = m_pSection->m_WordArray.GetAt(i); | |
| 573 CPVT_WordInfo* pOldWord = pWord; | |
| 574 if (i > 0) { | |
| 575 pOldWord = m_pSection->m_WordArray.GetAt(i - 1); | |
| 576 } | |
| 577 if (pWord) { | |
| 578 if (bTypeset) { | |
| 579 fLineAscent = | |
| 580 std::max(fLineAscent, m_pVT->GetWordAscent(*pWord, TRUE)); | |
| 581 fLineDescent = | |
| 582 std::min(fLineDescent, m_pVT->GetWordDescent(*pWord, TRUE)); | |
| 583 fWordWidth = m_pVT->GetWordWidth(*pWord); | |
| 584 } else { | |
| 585 fLineAscent = | |
| 586 std::max(fLineAscent, m_pVT->GetWordAscent(*pWord, fFontSize)); | |
| 587 fLineDescent = | |
| 588 std::min(fLineDescent, m_pVT->GetWordDescent(*pWord, fFontSize)); | |
| 589 fWordWidth = m_pVT->GetWordWidth( | |
| 590 pWord->nFontIndex, pWord->Word, m_pVT->m_wSubWord, | |
| 591 m_pVT->m_fCharSpace, m_pVT->m_nHorzScale, fFontSize, | |
| 592 pWord->fWordTail, 0); | |
| 593 } | |
| 594 if (!bOpened) { | |
| 595 if (IsOpenStylePunctuation(pWord->Word)) { | |
| 596 bOpened = TRUE; | |
| 597 bFullWord = TRUE; | |
| 598 } else if (pOldWord) { | |
| 599 if (NeedDivision(pOldWord->Word, pWord->Word)) { | |
| 600 bFullWord = TRUE; | |
| 601 } | |
| 602 } | |
| 603 } else { | |
| 604 if (!IsSpace(pWord->Word) && !IsOpenStylePunctuation(pWord->Word)) { | |
| 605 bOpened = FALSE; | |
| 606 } | |
| 607 } | |
| 608 if (bFullWord) { | |
| 609 bFullWord = FALSE; | |
| 610 if (nCharIndex > 0) { | |
| 611 nLineFullWordIndex++; | |
| 612 } | |
| 613 nWordStartPos = i; | |
| 614 fBackupLineWidth = fLineWidth; | |
| 615 fBackupLineAscent = fLineAscent; | |
| 616 fBackupLineDescent = fLineDescent; | |
| 617 } | |
| 618 nCharIndex++; | |
| 619 } | |
| 620 if (m_pVT->m_bLimitWidth && fTypesetWidth > 0 && | |
| 621 fLineWidth + fWordWidth > fTypesetWidth) { | |
| 622 if (nLineFullWordIndex > 0) { | |
| 623 i = nWordStartPos; | |
| 624 fLineWidth = fBackupLineWidth; | |
| 625 fLineAscent = fBackupLineAscent; | |
| 626 fLineDescent = fBackupLineDescent; | |
| 627 } | |
| 628 if (nCharIndex == 1) { | |
| 629 fLineWidth = fWordWidth; | |
| 630 i++; | |
| 631 } | |
| 632 nLineTail = i - 1; | |
| 633 if (bTypeset) { | |
| 634 line.nBeginWordIndex = nLineHead; | |
| 635 line.nEndWordIndex = nLineTail; | |
| 636 line.nTotalWord = nLineTail - nLineHead + 1; | |
| 637 line.fLineWidth = fLineWidth; | |
| 638 line.fLineAscent = fLineAscent; | |
| 639 line.fLineDescent = fLineDescent; | |
| 640 m_pSection->AddLine(line); | |
| 641 } | |
| 642 fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo)); | |
| 643 fMaxY -= fLineDescent; | |
| 644 fMaxX = std::max(fLineWidth, fMaxX); | |
| 645 nLineHead = i; | |
| 646 fLineWidth = 0.0f; | |
| 647 fLineAscent = 0.0f; | |
| 648 fLineDescent = 0.0f; | |
| 649 nCharIndex = 0; | |
| 650 nLineFullWordIndex = 0; | |
| 651 bFullWord = FALSE; | |
| 652 } else { | |
| 653 fLineWidth += fWordWidth; | |
| 654 i++; | |
| 655 } | |
| 656 } | |
| 657 if (nLineHead <= nTotalWords - 1) { | |
| 658 nLineTail = nTotalWords - 1; | |
| 659 if (bTypeset) { | |
| 660 line.nBeginWordIndex = nLineHead; | |
| 661 line.nEndWordIndex = nLineTail; | |
| 662 line.nTotalWord = nLineTail - nLineHead + 1; | |
| 663 line.fLineWidth = fLineWidth; | |
| 664 line.fLineAscent = fLineAscent; | |
| 665 line.fLineDescent = fLineDescent; | |
| 666 m_pSection->AddLine(line); | |
| 667 } | |
| 668 fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo)); | |
| 669 fMaxY -= fLineDescent; | |
| 670 fMaxX = std::max(fLineWidth, fMaxX); | |
| 671 } | |
| 672 } else { | |
| 673 if (bTypeset) { | |
| 674 fLineAscent = m_pVT->GetLineAscent(m_pSection->m_SecInfo); | |
| 675 fLineDescent = m_pVT->GetLineDescent(m_pSection->m_SecInfo); | |
| 676 } else { | |
| 677 fLineAscent = | |
| 678 m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), fFontSize); | |
| 679 fLineDescent = | |
| 680 m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), fFontSize); | |
| 681 } | |
| 682 if (bTypeset) { | |
| 683 line.nBeginWordIndex = -1; | |
| 684 line.nEndWordIndex = -1; | |
| 685 line.nTotalWord = 0; | |
| 686 line.fLineWidth = 0; | |
| 687 line.fLineAscent = fLineAscent; | |
| 688 line.fLineDescent = fLineDescent; | |
| 689 m_pSection->AddLine(line); | |
| 690 } | |
| 691 fMaxY += m_pVT->GetLineLeading(m_pSection->m_SecInfo) + fLineAscent - | |
| 692 fLineDescent; | |
| 693 } | |
| 694 m_rcRet = CPVT_FloatRect(0, 0, fMaxX, fMaxY); | |
| 695 } | |
| 696 void CTypeset::OutputLines() { | |
| 697 ASSERT(m_pVT); | |
| 698 ASSERT(m_pSection); | |
| 699 FX_FLOAT fMinX = 0.0f, fMinY = 0.0f, fMaxX = 0.0f, fMaxY = 0.0f; | |
| 700 FX_FLOAT fPosX = 0.0f, fPosY = 0.0f; | |
| 701 FX_FLOAT fLineIndent = m_pVT->GetLineIndent(m_pSection->m_SecInfo); | |
| 702 FX_FLOAT fTypesetWidth = std::max(m_pVT->GetPlateWidth() - fLineIndent, 0.0f); | |
| 703 switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) { | |
| 704 default: | |
| 705 case 0: | |
| 706 fMinX = 0.0f; | |
| 707 break; | |
| 708 case 1: | |
| 709 fMinX = (fTypesetWidth - m_rcRet.Width()) * VARIABLETEXT_HALF; | |
| 710 break; | |
| 711 case 2: | |
| 712 fMinX = fTypesetWidth - m_rcRet.Width(); | |
| 713 break; | |
| 714 } | |
| 715 fMaxX = fMinX + m_rcRet.Width(); | |
| 716 fMinY = 0.0f; | |
| 717 fMaxY = m_rcRet.Height(); | |
| 718 int32_t nTotalLines = m_pSection->m_LineArray.GetSize(); | |
| 719 if (nTotalLines > 0) { | |
| 720 m_pSection->m_SecInfo.nTotalLine = nTotalLines; | |
| 721 for (int32_t l = 0; l < nTotalLines; l++) { | |
| 722 if (CLine* pLine = m_pSection->m_LineArray.GetAt(l)) { | |
| 723 switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) { | |
| 724 default: | |
| 725 case 0: | |
| 726 fPosX = 0; | |
| 727 break; | |
| 728 case 1: | |
| 729 fPosX = (fTypesetWidth - pLine->m_LineInfo.fLineWidth) * | |
| 730 VARIABLETEXT_HALF; | |
| 731 break; | |
| 732 case 2: | |
| 733 fPosX = fTypesetWidth - pLine->m_LineInfo.fLineWidth; | |
| 734 break; | |
| 735 } | |
| 736 fPosX += fLineIndent; | |
| 737 fPosY += m_pVT->GetLineLeading(m_pSection->m_SecInfo); | |
| 738 fPosY += pLine->m_LineInfo.fLineAscent; | |
| 739 pLine->m_LineInfo.fLineX = fPosX - fMinX; | |
| 740 pLine->m_LineInfo.fLineY = fPosY - fMinY; | |
| 741 for (int32_t w = pLine->m_LineInfo.nBeginWordIndex; | |
| 742 w <= pLine->m_LineInfo.nEndWordIndex; w++) { | |
| 743 if (CPVT_WordInfo* pWord = m_pSection->m_WordArray.GetAt(w)) { | |
| 744 pWord->fWordX = fPosX - fMinX; | |
| 745 if (pWord->pWordProps) { | |
| 746 switch (pWord->pWordProps->nScriptType) { | |
| 747 default: | |
| 748 case CPDF_VariableText::ScriptType::Normal: | |
| 749 pWord->fWordY = fPosY - fMinY; | |
| 750 break; | |
| 751 case CPDF_VariableText::ScriptType::Super: | |
| 752 pWord->fWordY = fPosY - m_pVT->GetWordAscent(*pWord) - fMinY; | |
| 753 break; | |
| 754 case CPDF_VariableText::ScriptType::Sub: | |
| 755 pWord->fWordY = fPosY - m_pVT->GetWordDescent(*pWord) - fMinY; | |
| 756 break; | |
| 757 } | |
| 758 } else { | |
| 759 pWord->fWordY = fPosY - fMinY; | |
| 760 } | |
| 761 fPosX += m_pVT->GetWordWidth(*pWord); | |
| 762 } | |
| 763 } | |
| 764 fPosY -= pLine->m_LineInfo.fLineDescent; | |
| 765 } | |
| 766 } | |
| 767 } | |
| 768 m_rcRet = CPVT_FloatRect(fMinX, fMinY, fMaxX, fMaxY); | |
| 769 } | |
| OLD | NEW |