diff options
Diffstat (limited to 'core/src/reflow/reflowedtextpage.cpp')
-rw-r--r-- | core/src/reflow/reflowedtextpage.cpp | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/core/src/reflow/reflowedtextpage.cpp b/core/src/reflow/reflowedtextpage.cpp new file mode 100644 index 0000000000..a5ad0be948 --- /dev/null +++ b/core/src/reflow/reflowedtextpage.cpp @@ -0,0 +1,402 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "reflowedtextpage.h" +IPDF_TextPage* IPDF_TextPage::CreateReflowTextPage(IPDF_ReflowedPage* pRefPage) +{ + return FX_NEW CRF_TextPage(pRefPage); +} +CRF_TextPage::CRF_TextPage(IPDF_ReflowedPage* pRefPage) +{ + m_pRefPage = (CPDF_ReflowedPage*)(pRefPage); + m_pDataList = NULL; + m_CountBSArray = NULL; +} +CRF_TextPage::~CRF_TextPage() +{ + if(m_pDataList) { + delete m_pDataList; + m_pDataList = NULL; + } + if(m_CountBSArray) { + delete m_CountBSArray; + m_CountBSArray = NULL; + } +} +FX_BOOL CRF_TextPage::ParseTextPage() +{ + if(!m_pRefPage) { + return FALSE; + } + int count = m_pRefPage->m_pReflowed->GetSize(); + if(count < 500) { + m_pDataList = FX_NEW CRF_CharDataPtrArray(count); + } else { + m_pDataList = FX_NEW CRF_CharDataPtrArray(500); + } + if (NULL == m_pDataList) { + return FALSE; + } + for(int i = 0; i < count; i++) { + CRF_Data* pData = (*(m_pRefPage->m_pReflowed))[i]; + if(pData->GetType() == CRF_Data::Text) { + m_pDataList->Add((CRF_CharData*)pData); + } + } + m_CountBSArray = FX_NEW CFX_CountBSINT32Array(20); + if(NULL == m_CountBSArray) { + return FALSE; + } + return TRUE; +} +FX_BOOL CRF_TextPage::IsParsered() const +{ + if(m_pDataList) { + return TRUE; + } + return FALSE; +} +int CRF_TextPage::CharIndexFromTextIndex(int TextIndex) const +{ + return TextIndex; +} +int CRF_TextPage::TextIndexFromCharIndex(int CharIndex) const +{ + return CharIndex; +} + +int CRF_TextPage::CountChars() const +{ + if (NULL == m_pDataList) { + return -1; + } + return m_pDataList->GetSize(); +} +void CRF_TextPage::GetCharInfo(int index, FPDF_CHAR_INFO & info) const +{ + if(index >= CountChars() || index < 0 || !m_pDataList) { + return; + } + CRF_CharData* pData = (*m_pDataList)[index]; + FX_FLOAT ReltiveCorddDs = pData->m_pCharState->m_fDescent; + FX_FLOAT ReltiveCorddAs = pData->m_pCharState->m_fAscent; + info.m_Flag = CHAR_NORMAL; + info.m_pTextObj = pData->m_pCharState->m_pTextObj; + info.m_OriginX = pData->m_PosX; + info.m_OriginY = pData->m_PosY - ReltiveCorddDs; + info.m_FontSize = pData->m_pCharState->m_fFontSize; + CFX_FloatRect FloatRectTmp(pData->m_PosX, pData->m_PosY, pData->m_PosX + pData->m_Width, pData->m_PosY + ReltiveCorddAs - ReltiveCorddDs); + info.m_CharBox = FloatRectTmp; + CFX_WideString str = pData->m_pCharState->m_pFont->UnicodeFromCharCode(pData->m_CharCode); + if(!str.IsEmpty()) { + info.m_Unicode = str.GetAt(0); + } else { + info.m_Unicode = -1; + } + info.m_Charcode = (FX_WCHAR)pData->m_CharCode; + info.m_Matrix = CFX_Matrix(1, 0, 0, 1, 0, 0); +} +extern FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2, FX_FLOAT& interlow, FX_FLOAT& interhigh); +inline FX_BOOL _IsInsameline(const CFX_FloatRect& rectA, const CFX_FloatRect& rectB) +{ + if((rectA.top >= rectB.bottom && rectB.top >= rectA.bottom)) { + return TRUE; + } else { + return FALSE; + } +} +inline FX_BOOL _IsIntersect(const CFX_FloatRect& rectA, const CFX_FloatRect& rectB) +{ + FX_FLOAT interlow = .0f, interhigh = .0f; + if(GetIntersection(rectA.bottom, rectA.top, rectB.bottom, rectB.top, interlow, interhigh)) { + if(GetIntersection(rectA.left, rectA.right, rectB.left, rectB.right, interlow, interhigh)) { + return TRUE; + } else { + return FALSE; + } + } + return FALSE; +} +void CRF_TextPage::GetRectArray(int start, int nCount, CFX_RectArray& rectArray) const +{ + int indexlen = start + nCount; + FPDF_CHAR_INFO info; + FX_BOOL bstart = TRUE; + CFX_FloatRect recttmp; + int i; + for(i = start; i < indexlen; i++) { + GetCharInfo(i, info); + if(bstart) { + recttmp = info.m_CharBox; + bstart = FALSE; + } else if(_IsInsameline(recttmp, info.m_CharBox)) { + recttmp.right = info.m_CharBox.right; + if(info.m_CharBox.top > recttmp.top) { + recttmp.top = info.m_CharBox.top; + } + if(info.m_CharBox.bottom < recttmp.bottom) { + recttmp.bottom = info.m_CharBox.bottom; + } + } else { + rectArray.Add(recttmp); + recttmp = info.m_CharBox; + } + } + rectArray.Add(recttmp); +} +inline FX_FLOAT _GetDistance(CFX_FloatRect floatRect, CPDF_Point point) +{ + if(floatRect.right < point.x && floatRect.bottom > point.y) { + return FXSYS_sqrt(FXSYS_pow(point.x - floatRect.right, 2) + FXSYS_pow(floatRect.bottom - point.y, 2)); + } + if (floatRect.right < point.x && floatRect.top < point.y) { + return FXSYS_sqrt(FXSYS_pow(point.x - floatRect.right, 2) + FXSYS_pow(point.y - floatRect.top, 2)); + } + if(floatRect.left > point.x && floatRect.bottom > point.y) { + return FXSYS_sqrt(FXSYS_pow(floatRect.bottom - point.y, 2) + FXSYS_pow(floatRect.left - point.x, 2)); + } + if((floatRect.right > point.x || FXSYS_fabs(floatRect.right - point.x) <= 0.0001f) && + (floatRect.left < point.x || FXSYS_fabs(floatRect.left - point.x) <= 0.0001f) && floatRect.bottom > point.y) { + return FXSYS_fabs(floatRect.bottom - point.y); + } + if(floatRect.left > point.x && (floatRect.bottom < point.y || FXSYS_fabs(floatRect.bottom - point.y) <= 0.0001f) && + (floatRect.top > point.y || FXSYS_fabs(floatRect.top - point.y) <= 0.0001f)) { + return FXSYS_fabs(floatRect.left - point.x); + } + if(floatRect.left > point.x && floatRect.top < point.y) { + return FXSYS_sqrt(FXSYS_pow(floatRect.left - point.x, 2) + FXSYS_pow(point.y - floatRect.top, 2)); + } + if ((floatRect.left < point.x || FXSYS_fabs(floatRect.left - point.x) <= 0.0001f) && + (floatRect.right > point.x || FXSYS_fabs(floatRect.right - point.x) <= 0.0001f) && floatRect.top < point.y) { + return FXSYS_fabs(point.y - floatRect.top); + } + if(floatRect.right < point.x && (floatRect.top > point.y || FXSYS_fabs(floatRect.top - point.y) <= 0.0001f) && + (floatRect.bottom < point.y || FXSYS_fabs(floatRect.bottom - point.y) <= 0.0001f)) { + return point.x - floatRect.right; + } + return .0f; +} +int CRF_TextPage::GetIndexAtPos(CPDF_Point point, FX_FLOAT xTorelance, FX_FLOAT yTorelance) const +{ + int index = -1, i = 0, j = 0; + FPDF_CHAR_INFO info; + CFX_FloatRect rectTmp; + FX_FLOAT MinDistance = 1000, DistanceTmp = 0; + FX_FLOAT rect_bottom = point.x - xTorelance; + CFX_FloatRect TorelanceRect(rect_bottom <= 0 ? 0 : rect_bottom, point.y - yTorelance, point.x + xTorelance, point.y + yTorelance); + int count = CountChars(); + for(i = 0; i < count; i++) { + GetCharInfo(i, info); + rectTmp = info.m_CharBox; + if(rectTmp.Contains(point.x, point.y)) { + index = i; + break; + } else if(_IsIntersect(rectTmp, TorelanceRect)) { + DistanceTmp = _GetDistance(rectTmp, point); + if(DistanceTmp < MinDistance) { + MinDistance = DistanceTmp; + index = i; + } + } + } + return index; +} +int CRF_TextPage::GetIndexAtPos(FX_FLOAT x, FX_FLOAT y, FX_FLOAT xTorelance, FX_FLOAT yTorelance) const +{ + int index = 0; + CPDF_Point point(x, y); + if((index = GetIndexAtPos(point, xTorelance, yTorelance)) < 0) { + return -1; + } else { + return index; + } +} +int CRF_TextPage::GetOrderByDirection(int index, int direction) const +{ + return -1; +} +CFX_WideString CRF_TextPage::GetTextByRect(CFX_FloatRect rect) const +{ + int count; + FPDF_CHAR_INFO info; + CFX_WideString str; + CFX_FloatRect Recttmp; + FX_BOOL bstart = TRUE; + count = CountChars(); + if(rect.IsEmpty()) { + return L""; + } + for(int i = 0; i < count; i++) { + GetCharInfo(i, info); + if(_IsIntersect(rect, info.m_CharBox)) { + if(bstart) { + Recttmp = info.m_CharBox; + str += info.m_Unicode; + bstart = FALSE; + } else if(_IsInsameline(Recttmp, info.m_CharBox)) { + str += info.m_Unicode; + } else { + str += L"\r\n"; + Recttmp = info.m_CharBox; + str += info.m_Unicode; + } + } + } + if(str.IsEmpty()) { + return L""; + } else { + return str; + } +} +void CRF_TextPage::GetRectsArrayByRect(CFX_FloatRect rect, CFX_RectArray& resRectArray) const +{ + int count, i; + FX_BOOL bstart = TRUE; + FPDF_CHAR_INFO info; + CFX_FloatRect recttmp; + count = CountChars(); + for(i = 0; i < count; i++) { + GetCharInfo(i, info); + if(_IsIntersect(rect, info.m_CharBox)) { + if(bstart) { + recttmp = info.m_CharBox; + bstart = FALSE; + } else if(_IsInsameline(recttmp, info.m_CharBox)) { + recttmp.right = info.m_CharBox.right; + if(info.m_CharBox.top > recttmp.top) { + recttmp.top = info.m_CharBox.top; + } + if(info.m_CharBox.bottom < recttmp.bottom) { + recttmp.bottom = info.m_CharBox.bottom; + } + } else { + resRectArray.Add(recttmp); + recttmp = info.m_CharBox; + } + } + } + resRectArray.Add(recttmp); +} +int CRF_TextPage::CountRects(int start, int nCount) +{ + m_rectArray.RemoveAll(); + GetRectArray(start, nCount, m_rectArray); + return m_rectArray.GetSize(); +} +void CRF_TextPage::GetRect(int rectIndex, FX_FLOAT& left, FX_FLOAT& top, FX_FLOAT& right, FX_FLOAT &bottom) const +{ + if(m_rectArray.GetSize() <= rectIndex) { + return; + } + left = m_rectArray[rectIndex].left; + top = m_rectArray[rectIndex].top; + right = m_rectArray[rectIndex].right; + bottom = m_rectArray[rectIndex].bottom; +} +FX_BOOL CRF_TextPage::GetBaselineRotate(int rectIndex, int& Rotate) +{ + Rotate = 0; + return TRUE; +} +FX_BOOL CRF_TextPage::GetBaselineRotate(CFX_FloatRect rect, int& Rotate) +{ + Rotate = 0; + return TRUE; +} +int CRF_TextPage::CountBoundedSegments(FX_FLOAT left, FX_FLOAT top, FX_FLOAT right, FX_FLOAT bottom, FX_BOOL bContains) +{ + if (!m_CountBSArray) { + return -1; + } + m_CountBSArray->RemoveAll(); + CFX_FloatRect floatrect(left, bottom, right, top); + int totalcount, i, j = 0, counttmp = 0; + FX_BOOL bstart = TRUE; + FPDF_CHAR_INFO info; + CFX_FloatRect recttmp; + totalcount = CountChars(); + for(i = 0; i < totalcount; i++) { + GetCharInfo(i, info); + if(_IsIntersect(floatrect, info.m_CharBox)) { + if(bstart) { + m_CountBSArray->Add(i); + counttmp = 1; + recttmp = info.m_CharBox; + bstart = FALSE; + } else if(_IsInsameline(recttmp, info.m_CharBox)) { + recttmp.right = info.m_CharBox.right; + if(info.m_CharBox.top > recttmp.top) { + recttmp.top = info.m_CharBox.top; + } + if(info.m_CharBox.bottom < recttmp.bottom) { + recttmp.bottom = info.m_CharBox.bottom; + } + counttmp ++; + } else { + m_CountBSArray->Add(counttmp); + m_CountBSArray->Add(i); + counttmp = 1; + j++; + recttmp = info.m_CharBox; + } + } + } + m_CountBSArray->Add(counttmp); + j++; + return j; +} +void CRF_TextPage::GetBoundedSegment(int index, int& start, int& count) const +{ + if (!m_CountBSArray) { + return; + } + if(m_CountBSArray->GetSize() <= index * 2) { + start = 0; + count = 0; + return; + } + start = *(int *)m_CountBSArray->GetAt(index * 2); + count = *(int *)m_CountBSArray->GetAt(index * 2 + 1); +} + +int CRF_TextPage::GetWordBreak(int index, int direction) const +{ + return -1; +} +CFX_WideString CRF_TextPage::GetPageText(int start, int nCount ) const +{ + if(nCount == -1) { + nCount = CountChars(); + start = 0; + } else if(nCount < 1) { + return L""; + } else if(start >= CountChars()) { + return L""; + } + int i, index = start + nCount; + FPDF_CHAR_INFO info; + CFX_WideString str; + CFX_FloatRect recttmp; + FX_BOOL bstart = TRUE; + for(i = start; i < index; i++) { + GetCharInfo(i, info); + if(bstart) { + recttmp = info.m_CharBox; + str += info.m_Unicode; + bstart = FALSE; + } else if (_IsInsameline(recttmp, info.m_CharBox)) { + str += info.m_Unicode; + } else { + str += L"\r\n"; + recttmp = info.m_CharBox; + str += info.m_Unicode; + } + } + if(str.IsEmpty()) { + return L""; + } + return str; +} |