OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 "core/fpdfdoc/csection.h" |
| 8 |
| 9 #include <algorithm> |
| 10 |
| 11 #include "core/fpdfdoc/cpvt_wordinfo.h" |
| 12 |
| 13 CSection::CSection(CPDF_VariableText* pVT) : m_pVT(pVT) {} |
| 14 |
| 15 CSection::~CSection() { |
| 16 ResetAll(); |
| 17 } |
| 18 |
| 19 void CSection::ResetAll() { |
| 20 ResetWordArray(); |
| 21 ResetLineArray(); |
| 22 } |
| 23 |
| 24 void CSection::ResetLineArray() { |
| 25 m_LineArray.RemoveAll(); |
| 26 } |
| 27 |
| 28 void CSection::ResetWordArray() { |
| 29 for (int32_t i = 0, sz = m_WordArray.GetSize(); i < sz; i++) { |
| 30 delete m_WordArray.GetAt(i); |
| 31 } |
| 32 m_WordArray.RemoveAll(); |
| 33 } |
| 34 |
| 35 void CSection::ResetLinePlace() { |
| 36 for (int32_t i = 0, sz = m_LineArray.GetSize(); i < sz; i++) { |
| 37 if (CLine* pLine = m_LineArray.GetAt(i)) { |
| 38 pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1); |
| 39 } |
| 40 } |
| 41 } |
| 42 |
| 43 CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace& place, |
| 44 const CPVT_WordInfo& wordinfo) { |
| 45 CPVT_WordInfo* pWord = new CPVT_WordInfo(wordinfo); |
| 46 int32_t nWordIndex = |
| 47 std::max(std::min(place.nWordIndex, m_WordArray.GetSize()), 0); |
| 48 if (nWordIndex == m_WordArray.GetSize()) { |
| 49 m_WordArray.Add(pWord); |
| 50 } else { |
| 51 m_WordArray.InsertAt(nWordIndex, pWord); |
| 52 } |
| 53 return place; |
| 54 } |
| 55 |
| 56 CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo& lineinfo) { |
| 57 return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.Add(lineinfo), -1); |
| 58 } |
| 59 |
| 60 CPVT_FloatRect CSection::Rearrange() { |
| 61 if (m_pVT->m_nCharArray > 0) { |
| 62 return CTypeset(this).CharArray(); |
| 63 } |
| 64 return CTypeset(this).Typeset(); |
| 65 } |
| 66 |
| 67 CFX_SizeF CSection::GetSectionSize(FX_FLOAT fFontSize) { |
| 68 return CTypeset(this).GetEditSize(fFontSize); |
| 69 } |
| 70 |
| 71 CPVT_WordPlace CSection::GetBeginWordPlace() const { |
| 72 if (CLine* pLine = m_LineArray.GetAt(0)) { |
| 73 return pLine->GetBeginWordPlace(); |
| 74 } |
| 75 return SecPlace; |
| 76 } |
| 77 |
| 78 CPVT_WordPlace CSection::GetEndWordPlace() const { |
| 79 if (CLine* pLine = m_LineArray.GetAt(m_LineArray.GetSize() - 1)) { |
| 80 return pLine->GetEndWordPlace(); |
| 81 } |
| 82 return SecPlace; |
| 83 } |
| 84 |
| 85 CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace& place) const { |
| 86 if (place.nLineIndex < 0) { |
| 87 return GetBeginWordPlace(); |
| 88 } |
| 89 if (place.nLineIndex >= m_LineArray.GetSize()) { |
| 90 return GetEndWordPlace(); |
| 91 } |
| 92 if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) { |
| 93 if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) { |
| 94 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1); |
| 95 } |
| 96 if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) { |
| 97 if (CLine* pPrevLine = m_LineArray.GetAt(place.nLineIndex - 1)) { |
| 98 return pPrevLine->GetEndWordPlace(); |
| 99 } |
| 100 } else { |
| 101 return pLine->GetPrevWordPlace(place); |
| 102 } |
| 103 } |
| 104 return place; |
| 105 } |
| 106 |
| 107 CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace& place) const { |
| 108 if (place.nLineIndex < 0) { |
| 109 return GetBeginWordPlace(); |
| 110 } |
| 111 if (place.nLineIndex >= m_LineArray.GetSize()) { |
| 112 return GetEndWordPlace(); |
| 113 } |
| 114 if (CLine* pLine = m_LineArray.GetAt(place.nLineIndex)) { |
| 115 if (place.nWordIndex >= pLine->m_LineInfo.nEndWordIndex) { |
| 116 if (CLine* pNextLine = m_LineArray.GetAt(place.nLineIndex + 1)) { |
| 117 return pNextLine->GetBeginWordPlace(); |
| 118 } |
| 119 } else { |
| 120 return pLine->GetNextWordPlace(place); |
| 121 } |
| 122 } |
| 123 return place; |
| 124 } |
| 125 |
| 126 void CSection::UpdateWordPlace(CPVT_WordPlace& place) const { |
| 127 int32_t nLeft = 0; |
| 128 int32_t nRight = m_LineArray.GetSize() - 1; |
| 129 int32_t nMid = (nLeft + nRight) / 2; |
| 130 while (nLeft <= nRight) { |
| 131 if (CLine* pLine = m_LineArray.GetAt(nMid)) { |
| 132 if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) { |
| 133 nRight = nMid - 1; |
| 134 nMid = (nLeft + nRight) / 2; |
| 135 } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) { |
| 136 nLeft = nMid + 1; |
| 137 nMid = (nLeft + nRight) / 2; |
| 138 } else { |
| 139 place.nLineIndex = nMid; |
| 140 return; |
| 141 } |
| 142 } else { |
| 143 break; |
| 144 } |
| 145 } |
| 146 } |
| 147 |
| 148 CPVT_WordPlace CSection::SearchWordPlace(const CFX_FloatPoint& point) const { |
| 149 ASSERT(m_pVT); |
| 150 CPVT_WordPlace place = GetBeginWordPlace(); |
| 151 FX_BOOL bUp = TRUE; |
| 152 FX_BOOL bDown = TRUE; |
| 153 int32_t nLeft = 0; |
| 154 int32_t nRight = m_LineArray.GetSize() - 1; |
| 155 int32_t nMid = m_LineArray.GetSize() / 2; |
| 156 FX_FLOAT fTop = 0; |
| 157 FX_FLOAT fBottom = 0; |
| 158 while (nLeft <= nRight) { |
| 159 if (CLine* pLine = m_LineArray.GetAt(nMid)) { |
| 160 fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent - |
| 161 m_pVT->GetLineLeading(m_SecInfo); |
| 162 fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent; |
| 163 if (IsFloatBigger(point.y, fTop)) { |
| 164 bUp = FALSE; |
| 165 } |
| 166 if (IsFloatSmaller(point.y, fBottom)) { |
| 167 bDown = FALSE; |
| 168 } |
| 169 if (IsFloatSmaller(point.y, fTop)) { |
| 170 nRight = nMid - 1; |
| 171 nMid = (nLeft + nRight) / 2; |
| 172 continue; |
| 173 } else if (IsFloatBigger(point.y, fBottom)) { |
| 174 nLeft = nMid + 1; |
| 175 nMid = (nLeft + nRight) / 2; |
| 176 continue; |
| 177 } else { |
| 178 place = SearchWordPlace( |
| 179 point.x, |
| 180 CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), |
| 181 pLine->GetEndWordPlace())); |
| 182 place.nLineIndex = nMid; |
| 183 return place; |
| 184 } |
| 185 } |
| 186 } |
| 187 if (bUp) { |
| 188 place = GetBeginWordPlace(); |
| 189 } |
| 190 if (bDown) { |
| 191 place = GetEndWordPlace(); |
| 192 } |
| 193 return place; |
| 194 } |
| 195 |
| 196 CPVT_WordPlace CSection::SearchWordPlace( |
| 197 FX_FLOAT fx, |
| 198 const CPVT_WordPlace& lineplace) const { |
| 199 if (CLine* pLine = m_LineArray.GetAt(lineplace.nLineIndex)) { |
| 200 return SearchWordPlace( |
| 201 fx - m_SecInfo.rcSection.left, |
| 202 CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), |
| 203 pLine->GetEndWordPlace())); |
| 204 } |
| 205 return GetBeginWordPlace(); |
| 206 } |
| 207 |
| 208 CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, |
| 209 const CPVT_WordRange& range) const { |
| 210 CPVT_WordPlace wordplace = range.BeginPos; |
| 211 wordplace.nWordIndex = -1; |
| 212 if (!m_pVT) { |
| 213 return wordplace; |
| 214 } |
| 215 int32_t nLeft = range.BeginPos.nWordIndex; |
| 216 int32_t nRight = range.EndPos.nWordIndex + 1; |
| 217 int32_t nMid = (nLeft + nRight) / 2; |
| 218 while (nLeft < nRight) { |
| 219 if (nMid == nLeft) { |
| 220 break; |
| 221 } |
| 222 if (nMid == nRight) { |
| 223 nMid--; |
| 224 break; |
| 225 } |
| 226 if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) { |
| 227 if (fx > |
| 228 pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) { |
| 229 nLeft = nMid; |
| 230 nMid = (nLeft + nRight) / 2; |
| 231 continue; |
| 232 } else { |
| 233 nRight = nMid; |
| 234 nMid = (nLeft + nRight) / 2; |
| 235 continue; |
| 236 } |
| 237 } else { |
| 238 break; |
| 239 } |
| 240 } |
| 241 if (CPVT_WordInfo* pWord = m_WordArray.GetAt(nMid)) { |
| 242 if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * VARIABLETEXT_HALF) { |
| 243 wordplace.nWordIndex = nMid; |
| 244 } |
| 245 } |
| 246 return wordplace; |
| 247 } |
| 248 |
| 249 void CSection::ClearLeftWords(int32_t nWordIndex) { |
| 250 for (int32_t i = nWordIndex; i >= 0; i--) { |
| 251 delete m_WordArray.GetAt(i); |
| 252 m_WordArray.RemoveAt(i); |
| 253 } |
| 254 } |
| 255 |
| 256 void CSection::ClearRightWords(int32_t nWordIndex) { |
| 257 for (int32_t i = m_WordArray.GetSize() - 1; i > nWordIndex; i--) { |
| 258 delete m_WordArray.GetAt(i); |
| 259 m_WordArray.RemoveAt(i); |
| 260 } |
| 261 } |
| 262 |
| 263 void CSection::ClearMidWords(int32_t nBeginIndex, int32_t nEndIndex) { |
| 264 for (int32_t i = nEndIndex; i > nBeginIndex; i--) { |
| 265 delete m_WordArray.GetAt(i); |
| 266 m_WordArray.RemoveAt(i); |
| 267 } |
| 268 } |
| 269 |
| 270 void CSection::ClearWords(const CPVT_WordRange& PlaceRange) { |
| 271 CPVT_WordPlace SecBeginPos = GetBeginWordPlace(); |
| 272 CPVT_WordPlace SecEndPos = GetEndWordPlace(); |
| 273 if (PlaceRange.BeginPos.WordCmp(SecBeginPos) >= 0) { |
| 274 if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) { |
| 275 ClearMidWords(PlaceRange.BeginPos.nWordIndex, |
| 276 PlaceRange.EndPos.nWordIndex); |
| 277 } else { |
| 278 ClearRightWords(PlaceRange.BeginPos.nWordIndex); |
| 279 } |
| 280 } else if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) { |
| 281 ClearLeftWords(PlaceRange.EndPos.nWordIndex); |
| 282 } else { |
| 283 ResetWordArray(); |
| 284 } |
| 285 } |
| 286 |
| 287 void CSection::ClearWord(const CPVT_WordPlace& place) { |
| 288 delete m_WordArray.GetAt(place.nWordIndex); |
| 289 m_WordArray.RemoveAt(place.nWordIndex); |
| 290 } |
OLD | NEW |