Revert "FX Bool considered harmful, part 3"
[pdfium.git] / core / src / fpdftext / fpdf_text_int.cpp
index dea5722..c1aaad8 100644 (file)
@@ -1,16 +1,24 @@
 // 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 "../../include/fpdfapi/fpdf_resource.h"
+#include <ctype.h>
+#include <algorithm>
+
+#include "../../../third_party/base/nonstd_unique_ptr.h"
+#include "../../include/fpdfapi/fpdf_module.h"
+#include "../../include/fpdfapi/fpdf_page.h"
 #include "../../include/fpdfapi/fpdf_pageobj.h"
+#include "../../include/fpdfapi/fpdf_resource.h"
 #include "../../include/fpdftext/fpdf_text.h"
-#include "../../include/fpdfapi/fpdf_page.h"
-#include "../../include/fpdfapi/fpdf_module.h"
-#include <ctype.h>
+#include "../../include/fxcrt/fx_arb.h"
+#include "../../include/fxcrt/fx_ucd.h"
 #include "text_int.h"
+
+namespace {
+
 FX_BOOL _IsIgnoreSpaceCharacter(FX_WCHAR curChar)
 {
     if(curChar < 255 ) {
@@ -29,35 +37,76 @@ FX_BOOL _IsIgnoreSpaceCharacter(FX_WCHAR curChar)
     }
     return TRUE;
 }
+
+FX_FLOAT _NormalizeThreshold(FX_FLOAT threshold)
+{
+    if (threshold < 300) {
+        return threshold / 2.0f;
+    }
+    if (threshold < 500) {
+        return threshold / 4.0f;
+    }
+    if (threshold < 700) {
+        return threshold / 5.0f;
+    }
+    return threshold / 6.0f;
+}
+
+FX_FLOAT _CalculateBaseSpace(const CPDF_TextObject* pTextObj,
+                             const CFX_AffineMatrix& matrix)
+{
+    FX_FLOAT baseSpace = 0.0;
+    const int nItems = pTextObj->CountItems();
+    if (pTextObj->m_TextState.GetObject()->m_CharSpace && nItems >= 3) {
+        FX_BOOL bAllChar = TRUE;
+        FX_FLOAT spacing = matrix.TransformDistance(
+            pTextObj->m_TextState.GetObject()->m_CharSpace);
+        baseSpace = spacing;
+        for (int i = 0; i < nItems; i++) {
+            CPDF_TextObjectItem item;
+            pTextObj->GetItemInfo(i, &item);
+            if (item.m_CharCode == (FX_DWORD) - 1) {
+                FX_FLOAT fontsize_h = pTextObj->m_TextState.GetFontSizeH();
+                FX_FLOAT kerning = -fontsize_h * item.m_OriginX / 1000;
+                baseSpace = std::min(baseSpace, kerning + spacing);
+                bAllChar = FALSE;
+            }
+        }
+        if (baseSpace < 0.0 || (nItems == 3 && !bAllChar)) {
+            baseSpace = 0.0;
+        }
+    }
+    return baseSpace;
+}
+
+}  // namespace
+
 CPDFText_ParseOptions::CPDFText_ParseOptions()
     : m_bGetCharCodeOnly(FALSE), m_bNormalizeObjs(TRUE), m_bOutputHyphen(FALSE)
 {
 }
 IPDF_TextPage* IPDF_TextPage::CreateTextPage(const CPDF_Page* pPage, CPDFText_ParseOptions ParserOptions)
 {
-    CPDF_TextPage* pTextPageEx = FX_NEW CPDF_TextPage(pPage, ParserOptions);
-    return pTextPageEx;
+    return new CPDF_TextPage(pPage, ParserOptions);
 }
 IPDF_TextPage* IPDF_TextPage::CreateTextPage(const CPDF_Page* pPage, int flags)
 {
-    CPDF_TextPage* pTextPage = FX_NEW CPDF_TextPage(pPage, flags);
-    return     pTextPage;
+    return new CPDF_TextPage(pPage, flags);
 }
 IPDF_TextPage* IPDF_TextPage::CreateTextPage(const CPDF_PageObjects* pObjs, int flags)
 {
-    CPDF_TextPage* pTextPage = FX_NEW CPDF_TextPage(pObjs, flags);
-    return     pTextPage;
+    return new CPDF_TextPage(pObjs, flags);
 }
 IPDF_TextPageFind*     IPDF_TextPageFind::CreatePageFind(const IPDF_TextPage* pTextPage)
 {
     if (!pTextPage) {
         return NULL;
     }
-    return FX_NEW CPDF_TextPageFind(pTextPage);
+    return new CPDF_TextPageFind(pTextPage);
 }
 IPDF_LinkExtract* IPDF_LinkExtract::CreateLinkExtract()
 {
-    return FX_NEW CPDF_LinkExtract();
+    return new CPDF_LinkExtract();
 }
 #define  TEXT_BLANK_CHAR               L' '
 #define  TEXT_LINEFEED_CHAR            L'\n'
@@ -112,12 +161,9 @@ void CPDF_TextPage::NormalizeObjects(FX_BOOL bNormalize)
 {
     m_ParseOptions.m_bNormalizeObjs = bNormalize;
 }
-FX_BOOL CPDF_TextPage::IsControlChar(PAGECHAR_INFO* pCharInfo)
+bool CPDF_TextPage::IsControlChar(const PAGECHAR_INFO& charInfo)
 {
-    if(!pCharInfo) {
-        return FALSE;
-    }
-    switch(pCharInfo->m_Unicode) {
+    switch (charInfo.m_Unicode) {
         case 0x2:
         case 0x3:
         case 0x93:
@@ -126,13 +172,9 @@ FX_BOOL CPDF_TextPage::IsControlChar(PAGECHAR_INFO* pCharInfo)
         case 0x97:
         case 0x98:
         case 0xfffe:
-            if(pCharInfo->m_Flag == FPDFTEXT_CHAR_HYPHEN) {
-                return FALSE;
-            } else {
-                return TRUE;
-            }
+            return charInfo.m_Flag != FPDFTEXT_CHAR_HYPHEN;
         default:
-            return FALSE;
+            return false;
     }
 }
 FX_BOOL CPDF_TextPage::ParseTextPage()
@@ -160,7 +202,7 @@ FX_BOOL CPDF_TextPage::ParseTextPage()
             if(charinfo.m_Flag == FPDFTEXT_CHAR_GENERATED) {
                 bNormal = TRUE;
             }
-            else if(charinfo.m_Unicode == 0 || IsControlChar(&charinfo))
+            else if(charinfo.m_Unicode == 0 || IsControlChar(charinfo))
                 bNormal = FALSE;
             else {
                 bNormal = TRUE;
@@ -445,141 +487,6 @@ int       CPDF_TextPage::GetIndexAtPos(FX_FLOAT x, FX_FLOAT y, FX_FLOAT xTorelance, FX
     CPDF_Point point(x, y);
     return GetIndexAtPos(point, xTorelance, yTorelance);
 }
-int CPDF_TextPage::GetOrderByDirection(int order, int direction) const
-{
-    if(m_ParseOptions.m_bGetCharCodeOnly) {
-        return -3;
-    }
-    if (!m_IsParsered) {
-        return -3;
-    }
-    if (direction == FPDFTEXT_RIGHT || direction == FPDFTEXT_LEFT) {
-        order += direction;
-        while(order >= 0 && order < m_charList.GetSize()) {
-            PAGECHAR_INFO cinfo = *(PAGECHAR_INFO*)m_charList.GetAt(order);
-            if (cinfo.m_Flag != FPDFTEXT_CHAR_GENERATED) {
-                break;
-            } else {
-                if (cinfo.m_Unicode == TEXT_LINEFEED_CHAR || cinfo.m_Unicode == TEXT_RETURN_CHAR) {
-                    order += direction;
-                } else {
-                    break;
-                }
-            }
-        }
-        if (order >= m_charList.GetSize()) {
-            order = -2;
-        }
-        return order;
-    }
-    PAGECHAR_INFO charinfo;
-    charinfo = *(PAGECHAR_INFO*)m_charList.GetAt(order);
-    CPDF_Point curPos(charinfo.m_OriginX, charinfo.m_OriginY);
-    FX_FLOAT difPosY = 0.0, minXdif = 1000;
-    int        minIndex = -2;
-    int index = order;
-    FX_FLOAT height = charinfo.m_CharBox.Height();
-    if (direction == FPDFTEXT_UP) {
-        minIndex = -1;
-        while (1) {
-            if (--index < 0)   {
-                return -1;
-            }
-            charinfo = *(PAGECHAR_INFO*)m_charList.GetAt(index);
-            if (FXSYS_fabs(charinfo.m_OriginY - curPos.y) > FX_MAX(height, charinfo.m_CharBox.Height()) / 2) {
-                difPosY = charinfo.m_OriginY;
-                minIndex = index;
-                break;
-            }
-        }
-        FX_FLOAT PreXdif = charinfo.m_OriginX - curPos.x;
-        minXdif = PreXdif;
-        if (PreXdif == 0)      {
-            return index;
-        }
-        FX_FLOAT curXdif = 0;
-        while (--index >= 0) {
-            charinfo = *(PAGECHAR_INFO*)m_charList.GetAt(index);
-            if (difPosY != charinfo.m_OriginY) {
-                break;
-            }
-            curXdif = charinfo.m_OriginX - curPos.x;
-            if (curXdif == 0) {
-                return index;
-            }
-            int signflag = 0;
-            if (curXdif > 0) {
-                signflag = 1;
-            } else {
-                signflag = -1;
-            }
-            if (signflag * PreXdif < 0) {
-                if (FXSYS_fabs(PreXdif) < FXSYS_fabs(curXdif)) {
-                    return index + 1;
-                } else {
-                    return index;
-                }
-            }
-            if (FXSYS_fabs(curXdif) < FXSYS_fabs(minXdif)) {
-                minIndex = index;
-                minXdif = curXdif;
-            }
-            PreXdif = curXdif;
-            if (difPosY != charinfo.m_OriginY) {
-                break;
-            }
-        }
-        return minIndex;
-    } else if(FPDFTEXT_DOWN) {
-        minIndex = -2;
-        while (1) {
-            if (++index > m_charList.GetSize() - 1)    {
-                return minIndex;
-            }
-            charinfo = *(PAGECHAR_INFO*)m_charList.GetAt(index);
-            if (FXSYS_fabs(charinfo.m_OriginY - curPos.y) > FX_MAX(height, charinfo.m_CharBox.Height()) / 2) {
-                difPosY = charinfo.m_OriginY;
-                minIndex = index;
-                break;
-            }
-        }
-        FX_FLOAT PreXdif = charinfo.m_OriginX - curPos.x;
-        minXdif = PreXdif;
-        if (PreXdif == 0)      {
-            return index;
-        }
-        FX_FLOAT curXdif = 0;
-        while (++index < m_charList.GetSize()) {
-            charinfo = *(PAGECHAR_INFO*)m_charList.GetAt(index);
-            if (difPosY != charinfo.m_OriginY) {
-                break;
-            }
-            curXdif = charinfo.m_OriginX - curPos.x;
-            if (curXdif == 0) {
-                return index;
-            }
-            int signflag = 0;
-            if (curXdif > 0) {
-                signflag = 1;
-            } else {
-                signflag = -1;
-            }
-            if (signflag * PreXdif < 0) {
-                if (FXSYS_fabs(PreXdif) < FXSYS_fabs(curXdif)) {
-                    return index - 1;
-                } else {
-                    return index;
-                }
-            }
-            if (FXSYS_fabs(curXdif) < FXSYS_fabs(minXdif)) {
-                minXdif = curXdif;
-                minIndex = index;
-            }
-            PreXdif = curXdif;
-        }
-        return minIndex;
-    }
-}
 void CPDF_TextPage::GetCharInfo(int index, FPDF_CHAR_INFO & info) const
 {
     if(m_ParseOptions.m_bGetCharCodeOnly) {
@@ -606,7 +513,7 @@ void CPDF_TextPage::GetCharInfo(int index, FPDF_CHAR_INFO & info) const
     info.m_Matrix.Copy(charinfo.m_Matrix);
     return;
 }
-void CPDF_TextPage::CheckMarkedContentObject(FX_INT32& start, FX_INT32& nCount) const
+void CPDF_TextPage::CheckMarkedContentObject(int32_t& start, int32_t& nCount) const
 {
     PAGECHAR_INFO charinfo = *(PAGECHAR_INFO*)m_charList.GetAt(start);
     PAGECHAR_INFO charinfo2 = *(PAGECHAR_INFO*)m_charList.GetAt(start + nCount - 1);
@@ -905,7 +812,6 @@ int CPDF_TextPage::GetWordBreak(int index, int direction) const
                 return breakPos;
             }
         }
-        return breakPos;
     } else if (direction == FPDFTEXT_RIGHT) {
         while (++breakPos < m_charList.GetSize()) {
             charinfo = *(PAGECHAR_INFO*)m_charList.GetAt(breakPos);
@@ -913,28 +819,27 @@ int CPDF_TextPage::GetWordBreak(int index, int direction) const
                 return breakPos;
             }
         }
-        return breakPos;
     }
     return breakPos;
 }
-FX_INT32 CPDF_TextPage::FindTextlineFlowDirection()
+int32_t CPDF_TextPage::FindTextlineFlowDirection()
 {
     if (!m_pPage)      {
         return -1;
     }
-    const FX_INT32 nPageWidth = (FX_INT32)((CPDF_Page*)m_pPage)->GetPageWidth();
-    const FX_INT32 nPageHeight = (FX_INT32)((CPDF_Page*)m_pPage)->GetPageHeight();
+    const int32_t nPageWidth = (int32_t)((CPDF_Page*)m_pPage)->GetPageWidth();
+    const int32_t nPageHeight = (int32_t)((CPDF_Page*)m_pPage)->GetPageHeight();
     CFX_ByteArray nHorizontalMask;
     if (!nHorizontalMask.SetSize(nPageWidth)) {
         return -1;
     }
-    FX_BYTE* pDataH = nHorizontalMask.GetData();
+    uint8_t* pDataH = nHorizontalMask.GetData();
     CFX_ByteArray nVerticalMask;
     if (!nVerticalMask.SetSize(nPageHeight)) {
         return -1;
     }
-    FX_BYTE* pDataV = nVerticalMask.GetData();
-    FX_INT32 index = 0;
+    uint8_t* pDataV = nVerticalMask.GetData();
+    int32_t index = 0;
     FX_FLOAT fLineHeight = 0.0f;
     CPDF_PageObject* pPageObj = NULL;
     FX_POSITION        pos = NULL;
@@ -950,22 +855,22 @@ FX_INT32 CPDF_TextPage::FindTextlineFlowDirection()
         if(PDFPAGE_TEXT != pPageObj->m_Type) {
             continue;
         }
-        FX_INT32 minH = (FX_INT32)pPageObj->m_Left < 0 ? 0 : (FX_INT32)pPageObj->m_Left;
-        FX_INT32 maxH = (FX_INT32)pPageObj->m_Right > nPageWidth ? nPageWidth : (FX_INT32)pPageObj->m_Right;
-        FX_INT32 minV = (FX_INT32)pPageObj->m_Bottom < 0 ? 0 : (FX_INT32)pPageObj->m_Bottom;
-        FX_INT32 maxV = (FX_INT32)pPageObj->m_Top > nPageHeight ? nPageHeight : (FX_INT32)pPageObj->m_Top;
+        int32_t minH = (int32_t)pPageObj->m_Left < 0 ? 0 : (int32_t)pPageObj->m_Left;
+        int32_t maxH = (int32_t)pPageObj->m_Right > nPageWidth ? nPageWidth : (int32_t)pPageObj->m_Right;
+        int32_t minV = (int32_t)pPageObj->m_Bottom < 0 ? 0 : (int32_t)pPageObj->m_Bottom;
+        int32_t maxV = (int32_t)pPageObj->m_Top > nPageHeight ? nPageHeight : (int32_t)pPageObj->m_Top;
         if (minH >= maxH || minV >= maxV) {
             continue;
         }
-        FXSYS_memset8(pDataH + minH, 1, maxH - minH);
-        FXSYS_memset8(pDataV + minV, 1, maxV - minV);
+        FXSYS_memset(pDataH + minH, 1, maxH - minH);
+        FXSYS_memset(pDataV + minV, 1, maxV - minV);
         if (fLineHeight <= 0.0f) {
             fLineHeight = pPageObj->m_Top - pPageObj->m_Bottom;
         }
         pPageObj = NULL;
     }
-    FX_INT32 nStartH = 0;
-    FX_INT32 nEndH = 0;
+    int32_t nStartH = 0;
+    int32_t nEndH = 0;
     FX_FLOAT nSumH = 0.0f;
     for (index = 0; index < nPageWidth; index++)
         if(1 == nHorizontalMask[index]) {
@@ -981,8 +886,8 @@ FX_INT32 CPDF_TextPage::FindTextlineFlowDirection()
         nSumH += nHorizontalMask[index];
     }
     nSumH /= nEndH - nStartH;
-    FX_INT32 nStartV = 0;
-    FX_INT32 nEndV = 0;
+    int32_t nStartV = 0;
+    int32_t nEndV = 0;
     FX_FLOAT nSumV = 0.0f;
     for (index = 0; index < nPageHeight; index++)
         if(1 == nVerticalMask[index]) {
@@ -998,10 +903,10 @@ FX_INT32 CPDF_TextPage::FindTextlineFlowDirection()
         nSumV += nVerticalMask[index];
     }
     nSumV /= nEndV - nStartV;
-    if ((nEndV - nStartV) < (FX_INT32)(2 * fLineHeight)) {
+    if ((nEndV - nStartV) < (int32_t)(2 * fLineHeight)) {
         return 0;
     }
-    if ((nEndH - nStartH) < (FX_INT32)(2 * fLineHeight)) {
+    if ((nEndH - nStartH) < (int32_t)(2 * fLineHeight)) {
         return 1;
     }
     if (nSumH > 0.8f) {
@@ -1095,8 +1000,8 @@ int CPDF_TextPage::GetCharWidth(FX_DWORD charCode, CPDF_Font* pFont) const
 }
 void CPDF_TextPage::OnPiece(IFX_BidiChar* pBidi, CFX_WideString& str)
 {
-    FX_INT32 start, count;
-    FX_INT32 ret = pBidi->GetBidiInfo(start, count);
+    int32_t start, count;
+    int32_t ret = pBidi->GetBidiInfo(start, count);
     if(ret == 2) {
         for(int i = start + count - 1; i >= start; i--) {
             m_TextBuf.AppendChar(str.GetAt(i));
@@ -1114,16 +1019,13 @@ void CPDF_TextPage::AddCharInfoByLRDirection(CFX_WideString& str, int i)
 {
     PAGECHAR_INFO Info = *(PAGECHAR_INFO*)m_TempCharList.GetAt(i);
     FX_WCHAR wChar = str.GetAt(i);
-    if(!IsControlChar(&Info)) {
+    if(!IsControlChar(Info)) {
         Info.m_Index = m_TextBuf.GetLength();
         if (wChar >= 0xFB00 && wChar <= 0xFB06) {
-            FX_LPWSTR pDst = NULL;
+            FX_WCHAR* pDst = NULL;
             FX_STRSIZE nCount = FX_Unicode_GetNormalization(wChar, pDst);
             if (nCount >= 1) {
                 pDst = FX_Alloc(FX_WCHAR, nCount);
-                if (!pDst) {
-                    return;
-                }
                 FX_Unicode_GetNormalization(wChar, pDst);
                 for (int nIndex = 0; nIndex < nCount; nIndex++) {
                     PAGECHAR_INFO Info2 = Info;
@@ -1149,16 +1051,13 @@ void CPDF_TextPage::AddCharInfoByLRDirection(CFX_WideString& str, int i)
 void CPDF_TextPage::AddCharInfoByRLDirection(CFX_WideString& str, int i)
 {
     PAGECHAR_INFO Info = *(PAGECHAR_INFO*)m_TempCharList.GetAt(i);
-    if(!IsControlChar(&Info)) {
+    if(!IsControlChar(Info)) {
         Info.m_Index = m_TextBuf.GetLength();
         FX_WCHAR wChar = FX_GetMirrorChar(str.GetAt(i), TRUE, FALSE);
-        FX_LPWSTR pDst = NULL;
+        FX_WCHAR* pDst = NULL;
         FX_STRSIZE nCount = FX_Unicode_GetNormalization(wChar, pDst);
         if (nCount >= 1) {
             pDst = FX_Alloc(FX_WCHAR, nCount);
-            if (!pDst) {
-                return;
-            }
             FX_Unicode_GetNormalization(wChar, pDst);
             for (int nIndex = 0; nIndex < nCount; nIndex++) {
                 PAGECHAR_INFO Info2 = Info;
@@ -1171,9 +1070,8 @@ void CPDF_TextPage::AddCharInfoByRLDirection(CFX_WideString& str, int i)
             }
             FX_Free(pDst);
             return;
-        } else {
-            Info.m_Unicode = wChar;
         }
+        Info.m_Unicode = wChar;
         m_TextBuf.AppendChar(Info.m_Unicode);
     } else {
         Info.m_Index = -1;
@@ -1188,20 +1086,20 @@ void CPDF_TextPage::CloseTempLine()
     if (count1 <= 0) {
         return;
     }
-    IFX_BidiChar* BidiChar = IFX_BidiChar::Create();
+    nonstd::unique_ptr<IFX_BidiChar> pBidiChar(IFX_BidiChar::Create());
     CFX_WideString str = m_TempTextBuf.GetWideString();
     CFX_WordArray order;
     FX_BOOL bR2L = FALSE;
-    FX_INT32 start = 0, count = 0, i = 0;
+    int32_t start = 0, count = 0;
     int nR2L = 0, nL2R = 0;
     FX_BOOL bPrevSpace = FALSE;
-    for (i = 0; i < str.GetLength(); i++) {
+    for (int i = 0; i < str.GetLength(); i++) {
         if(str.GetAt(i) == 32) {
             if(bPrevSpace) {
                 m_TempTextBuf.Delete(i, 1);
                 m_TempCharList.Delete(i);
                 str.Delete(i);
-                count1 --;
+                count1--;
                 i--;
                 continue;
             }
@@ -1209,8 +1107,8 @@ void CPDF_TextPage::CloseTempLine()
         } else {
             bPrevSpace = FALSE;
         }
-        if(BidiChar && BidiChar->AppendChar(str.GetAt(i))) {
-            FX_INT32 ret = BidiChar->GetBidiInfo(start, count);
+        if(pBidiChar->AppendChar(str.GetAt(i))) {
+            int32_t ret = pBidiChar->GetBidiInfo(start, count);
             order.Add(start);
             order.Add(count);
             order.Add(ret);
@@ -1223,8 +1121,8 @@ void CPDF_TextPage::CloseTempLine()
             }
         }
     }
-    if(BidiChar && BidiChar->EndChar()) {
-        FX_INT32 ret = BidiChar->GetBidiInfo(start, count);
+    if(pBidiChar->EndChar()) {
+        int32_t ret = pBidiChar->GetBidiInfo(start, count);
         order.Add(start);
         order.Add(count);
         order.Add(ret);
@@ -1239,38 +1137,38 @@ void CPDF_TextPage::CloseTempLine()
     if(nR2L > 0 && nR2L >= nL2R) {
         bR2L = TRUE;
     }
-    if(this->m_parserflag == FPDFTEXT_RLTB || bR2L) {
+    if (m_parserflag == FPDFTEXT_RLTB || bR2L) {
         int count = order.GetSize();
-        for(int j = count - 1; j > 0; j -= 3) {
-            int ret = order.GetAt(j);
-            int start = order.GetAt(j - 2);
-            int count1 = order.GetAt(j - 1);
+        for(int i = count - 1; i > 0; i -= 3) {
+            int ret = order.GetAt(i);
+            int start = order.GetAt(i - 2);
+            int count1 = order.GetAt(i - 1);
             if(ret == 2 || ret == 0) {
-                for(int i = start + count1 - 1; i >= start; i--) {
-                    AddCharInfoByRLDirection(str, i);
+                for(int j = start + count1 - 1; j >= start; j--) {
+                    AddCharInfoByRLDirection(str, j);
                 }
             } else {
-                i = j;
+                int j = i;
                 FX_BOOL bSymbol = FALSE;
-                while(i > 0 && order.GetAt(i) != 2) {
-                    bSymbol = !order.GetAt(i);
-                    i -= 3;
+                while(j > 0 && order.GetAt(j) != 2) {
+                    bSymbol = !order.GetAt(j);
+                    j -= 3;
                 }
                 int end = start + count1 ;
                 int n = 0;
                 if(bSymbol) {
-                    n = i + 6;
+                    n = j + 6;
                 } else {
-                    n = i + 3;
+                    n = j + 3;
                 }
-                if(n >= j) {
+                if(n >= i) {
                     for(int m = start; m < end; m++) {
                         AddCharInfoByLRDirection(str, m);
                     }
                 } else {
-                    i = j;
-                    j = n;
-                    for(; n <= i; n += 3) {
+                    j = i;
+                    i = n;
+                    for(; n <= j; n += 3) {
                         int start = order.GetAt(n - 2);
                         int count1 = order.GetAt(n - 1);
                         int end = start + count1 ;
@@ -1284,46 +1182,43 @@ void CPDF_TextPage::CloseTempLine()
     } else {
         int count = order.GetSize();
         FX_BOOL bL2R = FALSE;
-        for(int j = 0; j < count; j += 3) {
-            int ret = order.GetAt(j + 2);
-            int start = order.GetAt(j);
-            int count1 = order.GetAt(j + 1);
-            if(ret == 2 || (j == 0 && ret == 0 && !bL2R)) {
-                int i = j + 3;
-                while(bR2L && i < count) {
-                    if(order.GetAt(i + 2) == 1) {
+        for(int i = 0; i < count; i += 3) {
+            int ret = order.GetAt(i + 2);
+            int start = order.GetAt(i);
+            int count1 = order.GetAt(i + 1);
+            if(ret == 2 || (i == 0 && ret == 0 && !bL2R)) {
+                int j = i + 3;
+                while(bR2L && j < count) {
+                    if(order.GetAt(j + 2) == 1) {
                         break;
                     } else {
-                        i += 3;
+                        j += 3;
                     }
                 }
-                if(i == 3) {
-                    j = -3;
+                if(j == 3) {
+                    i = -3;
                     bL2R = TRUE;
                     continue;
                 }
                 int end = m_TempCharList.GetSize() - 1;
-                if(i < count) {
-                    end = order.GetAt(i) - 1;
+                if(j < count) {
+                    end = order.GetAt(j) - 1;
                 }
-                j = i - 3;
+                i = j - 3;
                 for(int n = end; n >= start; n--) {
                     AddCharInfoByRLDirection(str, n);
                 }
             } else {
                 int end = start + count1 ;
-                for(int i = start; i < end; i++) {
-                    AddCharInfoByLRDirection(str, i);
+                for(int n = start; n < end; n++) {
+                    AddCharInfoByLRDirection(str, n);
                 }
             }
         }
     }
-    int ntext = m_TextBuf.GetSize();
-    ntext = m_charList.GetSize();
     order.RemoveAll();
     m_TempCharList.RemoveAll();
     m_TempTextBuf.Delete(0, m_TempTextBuf.GetLength());
-    BidiChar->Release();
 }
 void CPDF_TextPage::ProcessTextObject(CPDF_TextObject* pTextObj, const CFX_AffineMatrix& formMatrix, FX_POSITION ObjPos)
 {
@@ -1400,7 +1295,7 @@ void CPDF_TextPage::ProcessTextObject(CPDF_TextObject*    pTextObj, const CFX_Affin
         m_LineObj.Add(Obj);
     }
 }
-FX_INT32 CPDF_TextPage::PreMarkedContent(PDFTEXT_Obj Obj)
+int32_t CPDF_TextPage::PreMarkedContent(PDFTEXT_Obj Obj)
 {
     CPDF_TextObject* pTextObj = Obj.m_pTextObj;
     CPDF_ContentMarkData* pMarkData = (CPDF_ContentMarkData*)pTextObj->m_ContentMark.GetObject();
@@ -1457,8 +1352,8 @@ FX_INT32 CPDF_TextPage::PreMarkedContent(PDFTEXT_Obj Obj)
         return FPDFTEXT_MC_PASS;
     }
     bExist = FALSE;
-    for (FX_STRSIZE j = 0; j < nItems; j++) {
-        FX_WCHAR wChar = actText.GetAt(j);
+    for (FX_STRSIZE i = 0; i < nItems; i++) {
+        FX_WCHAR wChar = actText.GetAt(i);
         if ((wChar > 0x80 && wChar < 0xFFFD) || (wChar <= 0x80 && isprint(wChar))) {
             bExist = TRUE;
             break;
@@ -1560,7 +1455,7 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj)
     CFX_AffineMatrix matrix;
     pTextObj->GetTextMatrix(&matrix);
     matrix.Concat(formMatrix);
-    FX_INT32 bPreMKC = PreMarkedContent(Obj);
+    int32_t bPreMKC = PreMarkedContent(Obj);
     if (FPDFTEXT_MC_DONE == bPreMKC) {
         m_pPreTextObj = pTextObj;
         m_perMatrix.Copy(formMatrix);
@@ -1607,7 +1502,7 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj)
                 }
             }
         } else if (result == 3 && !m_ParseOptions.m_bOutputHyphen) {
-            FX_INT32 nChars = pTextObj->CountChars();
+            int32_t nChars = pTextObj->CountChars();
             if (nChars == 1) {
                 CPDF_TextObjectItem item;
                 pTextObj->GetCharInfo(0, &item);
@@ -1642,76 +1537,15 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj)
     m_pPreTextObj = pTextObj;
     m_perMatrix.Copy(formMatrix);
     int nItems = pTextObj->CountItems();
-    FX_FLOAT spacing = 0;
-    FX_FLOAT baseSpace = 0.0;
-    FX_BOOL bAllChar = TRUE;
-    if (pTextObj->m_TextState.GetObject()->m_CharSpace && nItems >= 3) {
-        spacing = matrix.TransformDistance(pTextObj->m_TextState.GetObject()->m_CharSpace);
-        baseSpace = spacing;
-        for (int i = 0; i < nItems; i++) {
-            CPDF_TextObjectItem item;
-            pTextObj->GetItemInfo(i, &item);
-            if (item.m_CharCode == (FX_DWORD) - 1) {
-                FX_FLOAT fontsize_h = pTextObj->m_TextState.GetFontSizeH();
-                FX_FLOAT kerning = -fontsize_h * item.m_OriginX / 1000;
-                if(kerning + spacing < baseSpace) {
-                    baseSpace = kerning + spacing;
-                }
-                bAllChar = FALSE;
-            }
-        }
-        spacing = 0;
-        if(baseSpace < 0.0 || (nItems == 3 && !bAllChar)) {
-            baseSpace = 0.0;
-        }
-    }
+    FX_FLOAT baseSpace = _CalculateBaseSpace(pTextObj, matrix);
 
-    FX_BOOL bIsBidiAndMirrosInverse = FALSE;
-    IFX_BidiChar* BidiChar = IFX_BidiChar::Create();
-    FX_INT32 nR2L = 0;
-    FX_INT32 nL2R = 0;
-    FX_INT32 start = 0, count = 0;
-    CPDF_TextObjectItem item;
-    for (FX_INT32 i = 0; i < nItems; i++) {
-        pTextObj->GetItemInfo(i, &item);
-        if (item.m_CharCode == (FX_DWORD)-1) {
-            continue;
-        }
-        CFX_WideString wstrItem = pFont->UnicodeFromCharCode(item.m_CharCode);
-        FX_WCHAR wChar = wstrItem.GetAt(0);
-        if ((wstrItem.IsEmpty() || wChar == 0) && item.m_CharCode) {
-            wChar = (FX_WCHAR)item.m_CharCode;
-        }
-        if (!wChar) {
-            continue;
-        }
-        if (BidiChar && BidiChar->AppendChar(wChar)) {
-            FX_INT32 ret = BidiChar->GetBidiInfo(start, count);
-            if (ret == 2) {
-                nR2L++;
-            }
-            else if (ret == 1) {
-                nL2R++;
-            }
-        }
-    }
-    if (BidiChar && BidiChar->EndChar()) {
-        FX_INT32 ret = BidiChar->GetBidiInfo(start, count);
-        if (ret == 2) {
-            nR2L++;
-        }
-        else if (ret == 1) {
-            nL2R++;
-        }
-    }
-    FX_BOOL bR2L = FALSE;
-    if (nR2L > 0 && nR2L >= nL2R) {
-        bR2L = TRUE;
-    }
-    bIsBidiAndMirrosInverse = bR2L && (matrix.a * matrix.d - matrix.b * matrix.c) < 0;
-    FX_INT32 iBufStartAppend = m_TempTextBuf.GetLength();
-    FX_INT32 iCharListStartAppend = m_TempCharList.GetSize();
+    const FX_BOOL bR2L = IsRightToLeft(pTextObj, pFont, nItems);
+    const FX_BOOL bIsBidiAndMirrorInverse =
+        bR2L && (matrix.a * matrix.d - matrix.b * matrix.c) < 0;
+    int32_t iBufStartAppend = m_TempTextBuf.GetLength();
+    int32_t iCharListStartAppend = m_TempCharList.GetSize();
 
+    FX_FLOAT spacing = 0;
     for (int i = 0; i < nItems; i++) {
         CPDF_TextObjectItem item;
         PAGECHAR_INFO charinfo;
@@ -1754,15 +1588,7 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj)
                 threshold = fontsize_h;
                 int this_width = FXSYS_abs(GetCharWidth(item.m_CharCode, pFont));
                 threshold = this_width > last_width ? (FX_FLOAT)this_width : (FX_FLOAT)last_width;
-                int nDivide = 6;
-                if (threshold < 300) {
-                    nDivide = 2;
-                } else if (threshold < 500) {
-                    nDivide = 4;
-                } else if (threshold < 700) {
-                    nDivide = 5;
-                }
-                threshold = threshold / nDivide;
+                threshold = _NormalizeThreshold(threshold);
                 threshold = fontsize_h * threshold / 1000;
             }
             if (threshold && (spacing && spacing >= threshold) ) {
@@ -1825,15 +1651,17 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj)
             continue;
         } else {
             int nTotal = wstrItem.GetLength();
-            int n = 0;
             FX_BOOL bDel = FALSE;
-            while (n < m_TempCharList.GetSize() && n < 7) {
-                n++;
-                PAGECHAR_INFO* charinfo1 = (PAGECHAR_INFO*)m_TempCharList.GetAt(m_TempCharList.GetSize() - n);
+            const int count = std::min(m_TempCharList.GetSize(), 7);
+            FX_FLOAT threshold = charinfo.m_Matrix.TransformXDistance((FX_FLOAT)TEXT_CHARRATIO_GAPDELTA * pTextObj->GetFontSize());
+            for (int n = m_TempCharList.GetSize();
+                 n > m_TempCharList.GetSize() - count;
+                 n--) {
+                PAGECHAR_INFO* charinfo1 = (PAGECHAR_INFO*)m_TempCharList.GetAt(n - 1);
                 if(charinfo1->m_CharCode == charinfo.m_CharCode &&
                         charinfo1->m_pTextObj->GetFont() == charinfo.m_pTextObj->GetFont()  &&
-                        FXSYS_fabs(charinfo1->m_OriginX - charinfo.m_OriginX) < TEXT_CHARRATIO_GAPDELTA * pTextObj->GetFontSize()  &&
-                        FXSYS_fabs(charinfo1->m_OriginY - charinfo.m_OriginY) < TEXT_CHARRATIO_GAPDELTA * pTextObj->GetFontSize() ) {
+                        FXSYS_fabs(charinfo1->m_OriginX - charinfo.m_OriginX) < threshold  &&
+                        FXSYS_fabs(charinfo1->m_OriginY - charinfo.m_OriginY) < threshold) {
                     bDel = TRUE;
                     break;
                 }
@@ -1858,34 +1686,73 @@ void CPDF_TextPage::ProcessTextObject(PDFTEXT_Obj Obj)
             }
         }
     }
-    if (bIsBidiAndMirrosInverse) {
-        FX_INT32 i, j;
-        i = iCharListStartAppend;
-        j = m_TempCharList.GetSize() - 1;
-        PAGECHAR_INFO tempCharInfo;
-        FX_INT32 tempIndex = 0;
-        for (; i < j; i++, j--) {
-            tempCharInfo = m_TempCharList[i];
-            m_TempCharList[i] = m_TempCharList[j];
-            m_TempCharList[j] = tempCharInfo;
-            tempIndex = m_TempCharList[i].m_Index;
-            m_TempCharList[i].m_Index = m_TempCharList[j].m_Index;
-            m_TempCharList[j].m_Index = tempIndex;
+    if (bIsBidiAndMirrorInverse) {
+        SwapTempTextBuf(iCharListStartAppend, iBufStartAppend);
+    }
+}
+void CPDF_TextPage::SwapTempTextBuf(int32_t iCharListStartAppend,
+                                    int32_t iBufStartAppend)
+{
+    int32_t i, j;
+    i = iCharListStartAppend;
+    j = m_TempCharList.GetSize() - 1;
+    for (; i < j; i++, j--) {
+        std::swap(m_TempCharList[i], m_TempCharList[j]);
+        std::swap(m_TempCharList[i].m_Index, m_TempCharList[j].m_Index);
+    }
+    FX_WCHAR * pTempBuffer = m_TempTextBuf.GetBuffer();
+    i = iBufStartAppend;
+    j = m_TempTextBuf.GetLength() - 1;
+    for (; i < j; i++, j--) {
+        std::swap(pTempBuffer[i], pTempBuffer[j]);
+    }
+}
+FX_BOOL CPDF_TextPage::IsRightToLeft(const CPDF_TextObject* pTextObj,
+                                     const CPDF_Font* pFont,
+                                     int nItems) const
+{
+    nonstd::unique_ptr<IFX_BidiChar> pBidiChar(IFX_BidiChar::Create());
+    int32_t nR2L = 0;
+    int32_t nL2R = 0;
+    int32_t start = 0, count = 0;
+    CPDF_TextObjectItem item;
+    for (int32_t i = 0; i < nItems; i++) {
+        pTextObj->GetItemInfo(i, &item);
+        if (item.m_CharCode == (FX_DWORD)-1) {
+            continue;
+        }
+        CFX_WideString wstrItem = pFont->UnicodeFromCharCode(item.m_CharCode);
+        FX_WCHAR wChar = wstrItem.GetAt(0);
+        if ((wstrItem.IsEmpty() || wChar == 0) && item.m_CharCode) {
+            wChar = (FX_WCHAR)item.m_CharCode;
         }
-        FX_WCHAR * pTempBuffer = m_TempTextBuf.GetBuffer();
-        i = iBufStartAppend;
-        j = m_TempTextBuf.GetLength() - 1;
-        FX_WCHAR wTemp;
-        for (; i < j; i++, j--) {
-            wTemp = pTempBuffer[i];
-            pTempBuffer[i] = pTempBuffer[j];
-            pTempBuffer[j] = wTemp;
+        if (!wChar) {
+            continue;
+        }
+        if (pBidiChar->AppendChar(wChar)) {
+            int32_t ret = pBidiChar->GetBidiInfo(start, count);
+            if (ret == 2) {
+                nR2L++;
+            }
+            else if (ret == 1) {
+                nL2R++;
+            }
         }
     }
+    if (pBidiChar->EndChar()) {
+        int32_t ret = pBidiChar->GetBidiInfo(start, count);
+        if (ret == 2) {
+            nR2L++;
+        }
+        else if (ret == 1) {
+            nL2R++;
+        }
+    }
+    return (nR2L > 0 && nR2L >= nL2R);
 }
-FX_INT32 CPDF_TextPage::GetTextObjectWritingMode(const CPDF_TextObject* pTextObj)
+int32_t CPDF_TextPage::GetTextObjectWritingMode(const CPDF_TextObject* pTextObj)
 {
-    FX_INT32 nChars = pTextObj->CountChars();
+    int32_t nChars = pTextObj->CountChars();
     if (nChars == 1) {
         return m_TextlineDir;
     }
@@ -1905,11 +1772,9 @@ FX_INT32 CPDF_TextPage::GetTextObjectWritingMode(const CPDF_TextObject* pTextObj
     v.Set(dX, dY);
     v.Normalize();
     if (v.y <= 0.0872f) {
-        if (v.x <= 0.0872f) {
-            return m_TextlineDir;
-        }
-        return 0;
-    } else if (v.x <= 0.0872f) {
+        return v.x <= 0.0872f ? m_TextlineDir : 0;
+    }
+    if (v.x <= 0.0872f) {
         return 1;
     }
     return m_TextlineDir;
@@ -2049,7 +1914,7 @@ int CPDF_TextPage::ProcessInsertObject(const CPDF_TextObject* pObj, const CFX_Af
         }
         return 2;
     }
-    FX_INT32 nChars = pObj->CountChars();
+    int32_t nChars = pObj->CountChars();
     if (nChars == 1 && ( 0x2D == curChar || 0xAD == curChar))
         if (IsHyphen(curChar)) {
             return 3;
@@ -2218,13 +2083,16 @@ FX_BOOL CPDF_TextPage::IsLetter(FX_WCHAR unicode)
     return TRUE;
 }
 CPDF_TextPageFind::CPDF_TextPageFind(const IPDF_TextPage* pTextPage)
-    : m_pTextPage(NULL),
+    : m_pTextPage(pTextPage),
+      m_flags(0),
+      m_findNextStart(-1),
+      m_findPreStart(-1),
+      m_bMatchCase(FALSE),
+      m_bMatchWholeWord(FALSE),
+      m_resStart(0),
+      m_resEnd(-1),
       m_IsFind(FALSE)
 {
-    if (!pTextPage) {
-        return;
-    }
-    m_pTextPage = pTextPage;
     m_strText = m_pTextPage->GetPageText();
     int nCount = pTextPage->CountChars();
     if(nCount) {
@@ -2258,8 +2126,6 @@ CPDF_TextPageFind::CPDF_TextPageFind(const IPDF_TextPage* pTextPage)
     if(indexSize % 2) {
         m_CharIndex.RemoveAt(indexSize - 1);
     }
-    m_resStart = 0;
-    m_resEnd = -1;
 }
 int CPDF_TextPageFind::GetCharIndex(int index) const
 {
@@ -2362,7 +2228,7 @@ FX_BOOL CPDF_TextPageFind::FindNext()
             continue;
         }
         int endIndex;
-        nResultPos = m_strText.Find(csWord, nStartPos);
+        nResultPos = m_strText.Find(csWord.c_str(), nStartPos);
         if (nResultPos == -1) {
             m_IsFind = FALSE;
             return m_IsFind;
@@ -2479,7 +2345,7 @@ void CPDF_TextPageFind::ExtractFindWhat(const CFX_WideString& findwhat)
     int index = 0;
     while(1) {
         CFX_WideString csWord = TEXT_EMPTY;
-        int ret = ExtractSubString(csWord, findwhat, index, TEXT_BLANK_CHAR);
+        int ret = ExtractSubString(csWord, findwhat.c_str(), index, TEXT_BLANK_CHAR);
         if(csWord.IsEmpty()) {
             if(ret) {
                 m_csFindWhatArray.Add(CFX_WideString(L""));
@@ -2490,7 +2356,6 @@ void CPDF_TextPageFind::ExtractFindWhat(const CFX_WideString& findwhat)
             }
         }
         int pos = 0;
-        FX_BOOL bLastIgnore = FALSE;
         while(pos < csWord.GetLength()) {
             CFX_WideString curStr = csWord.Mid(pos, 1);
             FX_WCHAR curChar = csWord.GetAt(pos);
@@ -2510,10 +2375,7 @@ void CPDF_TextPageFind::ExtractFindWhat(const CFX_WideString& findwhat)
                 }
                 csWord = csWord.Right(csWord.GetLength() - pos - 1);
                 pos = 0;
-                bLastIgnore = TRUE;
                 continue;
-            } else {
-                bLastIgnore = FALSE;
             }
             pos++;
         }
@@ -2522,7 +2384,6 @@ void CPDF_TextPageFind::ExtractFindWhat(const CFX_WideString& findwhat)
         }
         index++;
     }
-    return;
 }
 FX_BOOL CPDF_TextPageFind::IsMatchWholeWord(const CFX_WideString& csPageText, int startPos, int endPos)
 {
@@ -2559,7 +2420,7 @@ FX_BOOL CPDF_TextPageFind::IsMatchWholeWord(const CFX_WideString& csPageText, in
     }
     return TRUE;
 }
-FX_BOOL CPDF_TextPageFind::ExtractSubString(CFX_WideString& rString, FX_LPCWSTR lpszFullString,
+FX_BOOL CPDF_TextPageFind::ExtractSubString(CFX_WideString& rString, const FX_WCHAR* lpszFullString,
         int iSubString, FX_WCHAR chSep)
 {
     if (lpszFullString == NULL) {
@@ -2576,11 +2437,11 @@ FX_BOOL CPDF_TextPageFind::ExtractSubString(CFX_WideString& rString, FX_LPCWSTR
             lpszFullString++;
         }
     }
-    FX_LPCWSTR lpchEnd = FXSYS_wcschr(lpszFullString, chSep);
+    const FX_WCHAR* lpchEnd = FXSYS_wcschr(lpszFullString, chSep);
     int nLen = (lpchEnd == NULL) ?
                (int)FXSYS_wcslen(lpszFullString) : (int)(lpchEnd - lpszFullString);
     ASSERT(nLen >= 0);
-    FXSYS_memcpy32(rString.GetBuffer(nLen), lpszFullString, nLen * sizeof(FX_WCHAR));
+    FXSYS_memcpy(rString.GetBuffer(nLen), lpszFullString, nLen * sizeof(FX_WCHAR));
     rString.ReleaseBuffer();
     return TRUE;
 }
@@ -2692,22 +2553,25 @@ FX_BOOL CPDF_LinkExtract::CheckWebLink(CFX_WideString& strBeCheck)
     if (str.Find(L"http://www.") != -1) {
         strBeCheck = strBeCheck.Right(str.GetLength() - str.Find(L"http://www."));
         return TRUE;
-    } else if (str.Find(L"http://") != -1) {
+    }
+    if (str.Find(L"http://") != -1) {
         strBeCheck = strBeCheck.Right(str.GetLength() - str.Find(L"http://"));
         return TRUE;
-    } else if (str.Find(L"https://www.") != -1) {
+    }
+    if (str.Find(L"https://www.") != -1) {
         strBeCheck = strBeCheck.Right(str.GetLength() - str.Find(L"https://www."));
         return TRUE;
-    } else if (str.Find(L"https://") != -1) {
+    }
+    if (str.Find(L"https://") != -1) {
         strBeCheck = strBeCheck.Right(str.GetLength() - str.Find(L"https://"));
         return TRUE;
-    } else if (str.Find(L"www.") != -1) {
+    }
+    if (str.Find(L"www.") != -1) {
         strBeCheck = strBeCheck.Right(str.GetLength() - str.Find(L"www."));
         strBeCheck = L"http://" + strBeCheck;
         return TRUE;
-    } else {
-        return FALSE;
     }
+    return FALSE;
 }
 FX_BOOL CPDF_LinkExtract::CheckMailLink(CFX_WideString& str)
 {
@@ -2789,11 +2653,7 @@ FX_BOOL CPDF_LinkExtract::CheckMailLink(CFX_WideString& str)
 }
 FX_BOOL CPDF_LinkExtract::AppendToLinkList(int start, int count, const CFX_WideString& strUrl)
 {
-    CPDF_LinkExt* linkInfo = NULL;
-    linkInfo = FX_NEW CPDF_LinkExt;
-    if (!linkInfo) {
-        return FALSE;
-    }
+    CPDF_LinkExt* linkInfo = new CPDF_LinkExt;
     linkInfo->m_strUrl = strUrl;
     linkInfo->m_Start = start;
     linkInfo->m_Count = count;