Home | History | Annotate | Download | only in reflow
      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 "reflowedtextpage.h"
      8 IPDF_TextPage*	IPDF_TextPage::CreateReflowTextPage(IPDF_ReflowedPage* pRefPage)
      9 {
     10     return FX_NEW CRF_TextPage(pRefPage);
     11 }
     12 CRF_TextPage::CRF_TextPage(IPDF_ReflowedPage* pRefPage)
     13 {
     14     m_pRefPage = (CPDF_ReflowedPage*)(pRefPage);
     15     m_pDataList = NULL;
     16     m_CountBSArray = NULL;
     17 }
     18 CRF_TextPage::~CRF_TextPage()
     19 {
     20     if(m_pDataList) {
     21         delete m_pDataList;
     22         m_pDataList = NULL;
     23     }
     24     if(m_CountBSArray) {
     25         delete m_CountBSArray;
     26         m_CountBSArray = NULL;
     27     }
     28 }
     29 FX_BOOL CRF_TextPage::ParseTextPage()
     30 {
     31     if(!m_pRefPage) {
     32         return FALSE;
     33     }
     34     int count = m_pRefPage->m_pReflowed->GetSize();
     35     if(count < 500) {
     36         m_pDataList = FX_NEW CRF_CharDataPtrArray(count);
     37     } else {
     38         m_pDataList = FX_NEW CRF_CharDataPtrArray(500);
     39     }
     40     if (NULL == m_pDataList) {
     41         return FALSE;
     42     }
     43     for(int i = 0; i < count; i++) {
     44         CRF_Data* pData = (*(m_pRefPage->m_pReflowed))[i];
     45         if(pData->GetType() == CRF_Data::Text) {
     46             m_pDataList->Add((CRF_CharData*)pData);
     47         }
     48     }
     49     m_CountBSArray = FX_NEW CFX_CountBSINT32Array(20);
     50     if(NULL == m_CountBSArray) {
     51         return FALSE;
     52     }
     53     return TRUE;
     54 }
     55 FX_BOOL	CRF_TextPage::IsParsered() const
     56 {
     57     if(m_pDataList) {
     58         return TRUE;
     59     }
     60     return FALSE;
     61 }
     62 int CRF_TextPage::CharIndexFromTextIndex(int TextIndex) const
     63 {
     64     return TextIndex;
     65 }
     66 int CRF_TextPage::TextIndexFromCharIndex(int CharIndex) const
     67 {
     68     return CharIndex;
     69 }
     70 
     71 int	CRF_TextPage::CountChars() const
     72 {
     73     if (NULL == m_pDataList) {
     74         return -1;
     75     }
     76     return m_pDataList->GetSize();
     77 }
     78 void CRF_TextPage::GetCharInfo(int index, FPDF_CHAR_INFO & info) const
     79 {
     80     if(index >= CountChars() || index < 0 || !m_pDataList) {
     81         return;
     82     }
     83     CRF_CharData* pData = (*m_pDataList)[index];
     84     FX_FLOAT ReltiveCorddDs = pData->m_pCharState->m_fDescent;
     85     FX_FLOAT ReltiveCorddAs = pData->m_pCharState->m_fAscent;
     86     info.m_Flag		= CHAR_NORMAL;
     87     info.m_pTextObj	= pData->m_pCharState->m_pTextObj;
     88     info.m_OriginX	= pData->m_PosX;
     89     info.m_OriginY	= pData->m_PosY - ReltiveCorddDs;
     90     info.m_FontSize	= pData->m_pCharState->m_fFontSize;
     91     CFX_FloatRect FloatRectTmp(pData->m_PosX, pData->m_PosY, pData->m_PosX + pData->m_Width, pData->m_PosY + ReltiveCorddAs - ReltiveCorddDs);
     92     info.m_CharBox	= FloatRectTmp;
     93     CFX_WideString str = pData->m_pCharState->m_pFont->UnicodeFromCharCode(pData->m_CharCode);
     94     if(!str.IsEmpty()) {
     95         info.m_Unicode	= str.GetAt(0);
     96     } else {
     97         info.m_Unicode = -1;
     98     }
     99     info.m_Charcode = (FX_WCHAR)pData->m_CharCode;
    100     info.m_Matrix = CFX_Matrix(1, 0, 0, 1, 0, 0);
    101 }
    102 extern FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2, FX_FLOAT& interlow, FX_FLOAT& interhigh);
    103 inline FX_BOOL _IsInsameline(const CFX_FloatRect& rectA, const CFX_FloatRect& rectB)
    104 {
    105     if((rectA.top >= rectB.bottom && rectB.top >= rectA.bottom)) {
    106         return TRUE;
    107     } else {
    108         return FALSE;
    109     }
    110 }
    111 inline FX_BOOL _IsIntersect(const CFX_FloatRect& rectA, const CFX_FloatRect& rectB)
    112 {
    113     FX_FLOAT interlow = .0f, interhigh = .0f;
    114     if(GetIntersection(rectA.bottom, rectA.top, rectB.bottom, rectB.top, interlow, interhigh)) {
    115         if(GetIntersection(rectA.left, rectA.right, rectB.left, rectB.right, interlow, interhigh)) {
    116             return TRUE;
    117         } else {
    118             return FALSE;
    119         }
    120     }
    121     return FALSE;
    122 }
    123 void CRF_TextPage::GetRectArray(int start, int nCount, CFX_RectArray& rectArray) const
    124 {
    125     int indexlen = start + nCount;
    126     FPDF_CHAR_INFO info;
    127     FX_BOOL bstart = TRUE;
    128     CFX_FloatRect recttmp;
    129     int i;
    130     for(i = start; i < indexlen; i++) {
    131         GetCharInfo(i, info);
    132         if(bstart) {
    133             recttmp = info.m_CharBox;
    134             bstart = FALSE;
    135         } else if(_IsInsameline(recttmp, info.m_CharBox)) {
    136             recttmp.right = info.m_CharBox.right;
    137             if(info.m_CharBox.top > recttmp.top) {
    138                 recttmp.top = info.m_CharBox.top;
    139             }
    140             if(info.m_CharBox.bottom < recttmp.bottom) {
    141                 recttmp.bottom = info.m_CharBox.bottom;
    142             }
    143         } else {
    144             rectArray.Add(recttmp);
    145             recttmp = info.m_CharBox;
    146         }
    147     }
    148     rectArray.Add(recttmp);
    149 }
    150 inline FX_FLOAT _GetDistance(CFX_FloatRect floatRect, CPDF_Point point)
    151 {
    152     if(floatRect.right < point.x && floatRect.bottom > point.y) {
    153         return FXSYS_sqrt(FXSYS_pow(point.x - floatRect.right, 2) + FXSYS_pow(floatRect.bottom - point.y, 2));
    154     }
    155     if (floatRect.right < point.x && floatRect.top < point.y) {
    156         return FXSYS_sqrt(FXSYS_pow(point.x - floatRect.right, 2) + FXSYS_pow(point.y - floatRect.top, 2));
    157     }
    158     if(floatRect.left > point.x && floatRect.bottom > point.y) {
    159         return FXSYS_sqrt(FXSYS_pow(floatRect.bottom - point.y, 2) + FXSYS_pow(floatRect.left - point.x, 2));
    160     }
    161     if((floatRect.right > point.x || FXSYS_fabs(floatRect.right - point.x) <= 0.0001f) &&
    162             (floatRect.left < point.x || FXSYS_fabs(floatRect.left - point.x) <= 0.0001f) && floatRect.bottom > point.y) {
    163         return FXSYS_fabs(floatRect.bottom - point.y);
    164     }
    165     if(floatRect.left > point.x && (floatRect.bottom < point.y || FXSYS_fabs(floatRect.bottom - point.y) <= 0.0001f) &&
    166             (floatRect.top > point.y || FXSYS_fabs(floatRect.top - point.y) <= 0.0001f)) {
    167         return FXSYS_fabs(floatRect.left - point.x);
    168     }
    169     if(floatRect.left > point.x && floatRect.top < point.y) {
    170         return FXSYS_sqrt(FXSYS_pow(floatRect.left - point.x, 2) + FXSYS_pow(point.y - floatRect.top, 2));
    171     }
    172     if ((floatRect.left < point.x || FXSYS_fabs(floatRect.left - point.x) <= 0.0001f) &&
    173             (floatRect.right > point.x || FXSYS_fabs(floatRect.right - point.x) <= 0.0001f) && floatRect.top < point.y) {
    174         return FXSYS_fabs(point.y - floatRect.top);
    175     }
    176     if(floatRect.right < point.x && (floatRect.top > point.y || FXSYS_fabs(floatRect.top - point.y) <= 0.0001f) &&
    177             (floatRect.bottom < point.y || FXSYS_fabs(floatRect.bottom - point.y) <= 0.0001f)) {
    178         return point.x - floatRect.right;
    179     }
    180     return .0f;
    181 }
    182 int CRF_TextPage::GetIndexAtPos(CPDF_Point point, FX_FLOAT xTorelance, FX_FLOAT yTorelance) const
    183 {
    184     int index = -1, i = 0, j = 0;
    185     FPDF_CHAR_INFO info;
    186     CFX_FloatRect rectTmp;
    187     FX_FLOAT MinDistance = 1000, DistanceTmp = 0;
    188     FX_FLOAT rect_bottom = point.x - xTorelance;
    189     CFX_FloatRect TorelanceRect(rect_bottom <= 0 ? 0 : rect_bottom, point.y - yTorelance, point.x + xTorelance, point.y + yTorelance);
    190     int count = CountChars();
    191     for(i = 0; i < count; i++) {
    192         GetCharInfo(i, info);
    193         rectTmp = info.m_CharBox;
    194         if(rectTmp.Contains(point.x, point.y)) {
    195             index = i;
    196             break;
    197         } else if(_IsIntersect(rectTmp, TorelanceRect)) {
    198             DistanceTmp = _GetDistance(rectTmp, point);
    199             if(DistanceTmp < MinDistance) {
    200                 MinDistance = DistanceTmp;
    201                 index = i;
    202             }
    203         }
    204     }
    205     return index;
    206 }
    207 int CRF_TextPage::GetIndexAtPos(FX_FLOAT x, FX_FLOAT y, FX_FLOAT xTorelance, FX_FLOAT yTorelance) const
    208 {
    209     int index = 0;
    210     CPDF_Point point(x, y);
    211     if((index = GetIndexAtPos(point, xTorelance, yTorelance)) < 0) {
    212         return -1;
    213     } else {
    214         return index;
    215     }
    216 }
    217 int CRF_TextPage::GetOrderByDirection(int index, int direction) const
    218 {
    219     return -1;
    220 }
    221 CFX_WideString CRF_TextPage::GetTextByRect(CFX_FloatRect rect) const
    222 {
    223     int count;
    224     FPDF_CHAR_INFO info;
    225     CFX_WideString str;
    226     CFX_FloatRect  Recttmp;
    227     FX_BOOL bstart = TRUE;
    228     count = CountChars();
    229     if(rect.IsEmpty()) {
    230         return L"";
    231     }
    232     for(int i = 0; i < count; i++) {
    233         GetCharInfo(i, info);
    234         if(_IsIntersect(rect, info.m_CharBox)) {
    235             if(bstart) {
    236                 Recttmp = info.m_CharBox;
    237                 str += info.m_Unicode;
    238                 bstart = FALSE;
    239             } else if(_IsInsameline(Recttmp, info.m_CharBox)) {
    240                 str += info.m_Unicode;
    241             } else {
    242                 str += L"\r\n";
    243                 Recttmp = info.m_CharBox;
    244                 str += info.m_Unicode;
    245             }
    246         }
    247     }
    248     if(str.IsEmpty()) {
    249         return L"";
    250     } else {
    251         return str;
    252     }
    253 }
    254 void CRF_TextPage::GetRectsArrayByRect(CFX_FloatRect rect, CFX_RectArray& resRectArray) const
    255 {
    256     int count, i;
    257     FX_BOOL bstart = TRUE;
    258     FPDF_CHAR_INFO info;
    259     CFX_FloatRect recttmp;
    260     count = CountChars();
    261     for(i = 0; i < count; i++) {
    262         GetCharInfo(i, info);
    263         if(_IsIntersect(rect, info.m_CharBox)) {
    264             if(bstart) {
    265                 recttmp = info.m_CharBox;
    266                 bstart = FALSE;
    267             } else if(_IsInsameline(recttmp, info.m_CharBox)) {
    268                 recttmp.right = info.m_CharBox.right;
    269                 if(info.m_CharBox.top > recttmp.top) {
    270                     recttmp.top = info.m_CharBox.top;
    271                 }
    272                 if(info.m_CharBox.bottom < recttmp.bottom) {
    273                     recttmp.bottom = info.m_CharBox.bottom;
    274                 }
    275             } else {
    276                 resRectArray.Add(recttmp);
    277                 recttmp = info.m_CharBox;
    278             }
    279         }
    280     }
    281     resRectArray.Add(recttmp);
    282 }
    283 int CRF_TextPage::CountRects(int start, int nCount)
    284 {
    285     m_rectArray.RemoveAll();
    286     GetRectArray(start, nCount, m_rectArray);
    287     return m_rectArray.GetSize();
    288 }
    289 void CRF_TextPage::GetRect(int rectIndex, FX_FLOAT& left, FX_FLOAT& top, FX_FLOAT& right, FX_FLOAT &bottom) const
    290 {
    291     if(m_rectArray.GetSize() <= rectIndex) {
    292         return;
    293     }
    294     left   = m_rectArray[rectIndex].left;
    295     top    = m_rectArray[rectIndex].top;
    296     right  = m_rectArray[rectIndex].right;
    297     bottom = m_rectArray[rectIndex].bottom;
    298 }
    299 FX_BOOL CRF_TextPage::GetBaselineRotate(int rectIndex, int& Rotate)
    300 {
    301     Rotate = 0;
    302     return TRUE;
    303 }
    304 FX_BOOL CRF_TextPage::GetBaselineRotate(CFX_FloatRect rect, int& Rotate)
    305 {
    306     Rotate = 0;
    307     return TRUE;
    308 }
    309 int CRF_TextPage::CountBoundedSegments(FX_FLOAT left, FX_FLOAT top, FX_FLOAT right, FX_FLOAT bottom, FX_BOOL bContains)
    310 {
    311     if (!m_CountBSArray) {
    312         return -1;
    313     }
    314     m_CountBSArray->RemoveAll();
    315     CFX_FloatRect floatrect(left, bottom, right, top);
    316     int totalcount, i, j = 0, counttmp = 0;
    317     FX_BOOL bstart = TRUE;
    318     FPDF_CHAR_INFO info;
    319     CFX_FloatRect recttmp;
    320     totalcount = CountChars();
    321     for(i = 0; i < totalcount; i++) {
    322         GetCharInfo(i, info);
    323         if(_IsIntersect(floatrect, info.m_CharBox)) {
    324             if(bstart) {
    325                 m_CountBSArray->Add(i);
    326                 counttmp = 1;
    327                 recttmp = info.m_CharBox;
    328                 bstart = FALSE;
    329             } else if(_IsInsameline(recttmp, info.m_CharBox)) {
    330                 recttmp.right = info.m_CharBox.right;
    331                 if(info.m_CharBox.top > recttmp.top) {
    332                     recttmp.top = info.m_CharBox.top;
    333                 }
    334                 if(info.m_CharBox.bottom < recttmp.bottom) {
    335                     recttmp.bottom = info.m_CharBox.bottom;
    336                 }
    337                 counttmp ++;
    338             } else {
    339                 m_CountBSArray->Add(counttmp);
    340                 m_CountBSArray->Add(i);
    341                 counttmp = 1;
    342                 j++;
    343                 recttmp = info.m_CharBox;
    344             }
    345         }
    346     }
    347     m_CountBSArray->Add(counttmp);
    348     j++;
    349     return j;
    350 }
    351 void CRF_TextPage::GetBoundedSegment(int index, int& start, int& count) const
    352 {
    353     if (!m_CountBSArray) {
    354         return;
    355     }
    356     if(m_CountBSArray->GetSize() <= index * 2) {
    357         start = 0;
    358         count = 0;
    359         return;
    360     }
    361     start = *(int *)m_CountBSArray->GetAt(index * 2);
    362     count = *(int *)m_CountBSArray->GetAt(index * 2 + 1);
    363 }
    364 
    365 int CRF_TextPage::GetWordBreak(int index, int direction) const
    366 {
    367     return -1;
    368 }
    369 CFX_WideString CRF_TextPage::GetPageText(int start, int nCount ) const
    370 {
    371     if(nCount == -1) {
    372         nCount = CountChars();
    373         start = 0;
    374     } else if(nCount < 1) {
    375         return L"";
    376     } else if(start >= CountChars()) {
    377         return L"";
    378     }
    379     int i, index = start + nCount;
    380     FPDF_CHAR_INFO info;
    381     CFX_WideString str;
    382     CFX_FloatRect recttmp;
    383     FX_BOOL bstart = TRUE;
    384     for(i = start; i < index; i++) {
    385         GetCharInfo(i, info);
    386         if(bstart) {
    387             recttmp = info.m_CharBox;
    388             str += info.m_Unicode;
    389             bstart = FALSE;
    390         } else if (_IsInsameline(recttmp, info.m_CharBox)) {
    391             str += info.m_Unicode;
    392         } else {
    393             str += L"\r\n";
    394             recttmp = info.m_CharBox;
    395             str += info.m_Unicode;
    396         }
    397     }
    398     if(str.IsEmpty()) {
    399         return L"";
    400     }
    401     return str;
    402 }
    403