Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / core / src / fpdfdoc / doc_vt.cpp
index 251173d..7ed5b4a 100644 (file)
-// Copyright 2014 PDFium Authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
\r
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
-\r
-#include "../../include/fpdfdoc/fpdf_doc.h"\r
-#include "../../include/fpdfdoc/fpdf_vt.h"\r
-#include "pdf_vt.h"\r
-const FX_BYTE gFontSizeSteps[] = {     4, 6, 8, 9, 10, 12, 14, 18, 20, 25,     30, 35, 40, 45, 50,     55, 60, 70, 80, 90,     100, 110, 120, 130, 144};\r
-#define PVT_RETURN_LENGTH                                      1\r
-#define PVT_DEFAULT_FONTSIZE                           18.0f\r
-#define PVTWORD_SCRIPT_NORMAL                          0\r
-#define PVTWORD_SCRIPT_SUPER                           1\r
-#define PVTWORD_SCRIPT_SUB                                     2\r
-#define        PVT_FONTSCALE                                           0.001f\r
-#define PVT_PERCENT                                                    0.01f\r
-#define PVT_HALF                                                       0.5f\r
-CLine::CLine()\r
-{\r
-}\r
-CLine::~CLine()\r
-{\r
-}\r
-CPVT_WordPlace CLine::GetBeginWordPlace() const\r
-{\r
-    return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, -1);\r
-}\r
-CPVT_WordPlace CLine::GetEndWordPlace() const\r
-{\r
-    return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, m_LineInfo.nEndWordIndex);\r
-}\r
-CPVT_WordPlace CLine::GetPrevWordPlace(const CPVT_WordPlace & place) const\r
-{\r
-    if (place.nWordIndex > m_LineInfo.nEndWordIndex) {\r
-        return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, m_LineInfo.nEndWordIndex);\r
-    }\r
-    return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, place.nWordIndex - 1);\r
-}\r
-CPVT_WordPlace CLine::GetNextWordPlace(const CPVT_WordPlace & place) const\r
-{\r
-    if (place.nWordIndex < m_LineInfo.nBeginWordIndex) {\r
-        return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, m_LineInfo.nBeginWordIndex);\r
-    }\r
-    return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, place.nWordIndex + 1);\r
-}\r
-CSection::CSection(CPDF_VariableText * pVT) : m_pVT(pVT)\r
-{\r
-}\r
-CSection::~CSection()\r
-{\r
-    ResetAll();\r
-}\r
-void CSection::ResetAll()\r
-{\r
-    ResetWordArray();\r
-    ResetLineArray();\r
-}\r
-void CSection::ResetLineArray()\r
-{\r
-    m_LineArray.RemoveAll();\r
-}\r
-void CSection::ResetWordArray()\r
-{\r
-    for (FX_INT32 i = 0, sz = m_WordArray.GetSize(); i < sz; i++) {\r
-        delete m_WordArray.GetAt(i);\r
-    }\r
-    m_WordArray.RemoveAll();\r
-}\r
-void CSection::ResetLinePlace()\r
-{\r
-    for (FX_INT32 i = 0, sz = m_LineArray.GetSize(); i < sz; i++) {\r
-        if (CLine * pLine = m_LineArray.GetAt(i)) {\r
-            pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1);\r
-        }\r
-    }\r
-}\r
-CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)\r
-{\r
-    if (CPVT_WordInfo * pWord = FX_NEW CPVT_WordInfo(wordinfo)) {\r
-        FX_INT32 nWordIndex = FPDF_MAX(FPDF_MIN(place.nWordIndex, this->m_WordArray.GetSize()), 0);\r
-        if (nWordIndex == m_WordArray.GetSize()) {\r
-            m_WordArray.Add(pWord);\r
-        } else {\r
-            m_WordArray.InsertAt(nWordIndex, pWord);\r
-        }\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo & lineinfo)\r
-{\r
-    return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.Add(lineinfo), -1);\r
-}\r
-CPVT_FloatRect CSection::Rearrange()\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    if (m_pVT->m_nCharArray > 0) {\r
-        return CTypeset(this).CharArray();\r
-    } else {\r
-        return CTypeset(this).Typeset();\r
-    }\r
-}\r
-CPVT_Size CSection::GetSectionSize(FX_FLOAT fFontSize)\r
-{\r
-    return CTypeset(this).GetEditSize(fFontSize);\r
-}\r
-CPVT_WordPlace CSection::GetBeginWordPlace() const\r
-{\r
-    if (CLine * pLine = m_LineArray.GetAt(0)) {\r
-        return pLine->GetBeginWordPlace();\r
-    } else {\r
-        return SecPlace;\r
-    }\r
-}\r
-CPVT_WordPlace CSection::GetEndWordPlace() const\r
-{\r
-    if (CLine * pLine = m_LineArray.GetAt(m_LineArray.GetSize() - 1)) {\r
-        return pLine->GetEndWordPlace();\r
-    } else {\r
-        return this->SecPlace;\r
-    }\r
-}\r
-CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace & place) const\r
-{\r
-    if (place.nLineIndex < 0) {\r
-        return GetBeginWordPlace();\r
-    }\r
-    if (place.nLineIndex >= m_LineArray.GetSize()) {\r
-        return GetEndWordPlace();\r
-    }\r
-    if (CLine * pLine = m_LineArray.GetAt(place.nLineIndex)) {\r
-        if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) {\r
-            return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);\r
-        } else if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {\r
-            if (CLine * pPrevLine = m_LineArray.GetAt(place.nLineIndex - 1)) {\r
-                return pPrevLine->GetEndWordPlace();\r
-            }\r
-        } else {\r
-            return pLine->GetPrevWordPlace(place);\r
-        }\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace & place) const\r
-{\r
-    if (place.nLineIndex < 0) {\r
-        return GetBeginWordPlace();\r
-    }\r
-    if (place.nLineIndex >= m_LineArray.GetSize()) {\r
-        return GetEndWordPlace();\r
-    }\r
-    if (CLine * pLine = m_LineArray.GetAt(place.nLineIndex)) {\r
-        if (place.nWordIndex >= pLine->m_LineInfo.nEndWordIndex) {\r
-            if (CLine * pNextLine = m_LineArray.GetAt(place.nLineIndex + 1)) {\r
-                return pNextLine->GetBeginWordPlace();\r
-            }\r
-        } else {\r
-            return pLine->GetNextWordPlace(place);\r
-        }\r
-    }\r
-    return place;\r
-}\r
-void CSection::UpdateWordPlace(CPVT_WordPlace & place) const\r
-{\r
-    FX_INT32 nLeft = 0;\r
-    FX_INT32 nRight = m_LineArray.GetSize() - 1;\r
-    FX_INT32 nMid = (nLeft + nRight) / 2;\r
-    while (nLeft <= nRight) {\r
-        if (CLine * pLine = m_LineArray.GetAt(nMid)) {\r
-            if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {\r
-                nRight = nMid - 1;\r
-                nMid = (nLeft + nRight) / 2;\r
-            } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) {\r
-                nLeft = nMid + 1;\r
-                nMid = (nLeft + nRight) / 2;\r
-            } else {\r
-                place.nLineIndex = nMid;\r
-                return;\r
-            }\r
-        } else {\r
-            break;\r
-        }\r
-    }\r
-}\r
-CPVT_WordPlace CSection::SearchWordPlace(const CPDF_Point & point) const\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    CPVT_WordPlace place = GetBeginWordPlace();\r
-    FX_BOOL bUp = TRUE;\r
-    FX_BOOL bDown = TRUE;\r
-    FX_INT32 nLeft = 0;\r
-    FX_INT32 nRight = m_LineArray.GetSize() - 1;\r
-    FX_INT32 nMid = m_LineArray.GetSize() / 2;\r
-    FX_FLOAT fTop = 0;\r
-    FX_FLOAT fBottom = 0;\r
-    while (nLeft <= nRight) {\r
-        if (CLine * pLine = m_LineArray.GetAt(nMid)) {\r
-            fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent - m_pVT->GetLineLeading(m_SecInfo);\r
-            fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent;\r
-            if (IsFloatBigger(point.y, fTop)) {\r
-                bUp = FALSE;\r
-            }\r
-            if (IsFloatSmaller(point.y, fBottom)) {\r
-                bDown = FALSE;\r
-            }\r
-            if (IsFloatSmaller(point.y, fTop)) {\r
-                nRight = nMid - 1;\r
-                nMid = (nLeft + nRight) / 2;\r
-                continue;\r
-            } else if (IsFloatBigger(point.y, fBottom)) {\r
-                nLeft = nMid + 1;\r
-                nMid = (nLeft + nRight) / 2;\r
-                continue;\r
-            } else {\r
-                place = SearchWordPlace(point.x,\r
-                                        CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), pLine->GetEndWordPlace())\r
-                                       );\r
-                place.nLineIndex = nMid;\r
-                return place;\r
-            }\r
-        }\r
-    }\r
-    if (bUp) {\r
-        place = GetBeginWordPlace();\r
-    }\r
-    if (bDown) {\r
-        place = GetEndWordPlace();\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, const CPVT_WordPlace & lineplace) const\r
-{\r
-    if (CLine * pLine = m_LineArray.GetAt(lineplace.nLineIndex)) {\r
-        return SearchWordPlace(fx - m_SecInfo.rcSection.left,\r
-                               CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), pLine->GetEndWordPlace()));\r
-    }\r
-    return GetBeginWordPlace();\r
-}\r
-CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, const CPVT_WordRange & range) const\r
-{\r
-    CPVT_WordPlace wordplace = range.BeginPos;\r
-    wordplace.nWordIndex = -1;\r
-    if (!m_pVT)        {\r
-        return wordplace;\r
-    }\r
-    FX_INT32 nLeft = range.BeginPos.nWordIndex;\r
-    FX_INT32 nRight = range.EndPos.nWordIndex + 1;\r
-    FX_INT32 nMid = (nLeft + nRight) / 2;\r
-    while (nLeft < nRight) {\r
-        if (nMid == nLeft) {\r
-            break;\r
-        }\r
-        if (nMid == nRight) {\r
-            nMid--;\r
-            break;\r
-        }\r
-        if (CPVT_WordInfo * pWord = m_WordArray.GetAt(nMid)) {\r
-            if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {\r
-                nLeft = nMid;\r
-                nMid = (nLeft + nRight) / 2;\r
-                continue;\r
-            } else {\r
-                nRight = nMid;\r
-                nMid = (nLeft + nRight) / 2;\r
-                continue;\r
-            }\r
-        } else {\r
-            break;\r
-        }\r
-    }\r
-    if (CPVT_WordInfo * pWord = m_WordArray.GetAt(nMid)) {\r
-        if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {\r
-            wordplace.nWordIndex = nMid;\r
-        }\r
-    }\r
-    return wordplace;\r
-}\r
-void CSection::ClearLeftWords(FX_INT32 nWordIndex)\r
-{\r
-    for (FX_INT32 i = nWordIndex; i >= 0; i--) {\r
-        delete m_WordArray.GetAt(i);\r
-        m_WordArray.RemoveAt(i);\r
-    }\r
-}\r
-void CSection::ClearRightWords(FX_INT32 nWordIndex)\r
-{\r
-    for (FX_INT32 i = m_WordArray.GetSize() - 1; i > nWordIndex; i--) {\r
-        delete m_WordArray.GetAt(i);\r
-        m_WordArray.RemoveAt(i);\r
-    }\r
-}\r
-void CSection::ClearMidWords(FX_INT32 nBeginIndex, FX_INT32 nEndIndex)\r
-{\r
-    for (FX_INT32 i = nEndIndex; i > nBeginIndex; i--) {\r
-        delete m_WordArray.GetAt(i);\r
-        m_WordArray.RemoveAt(i);\r
-    }\r
-}\r
-void CSection::ClearWords(const CPVT_WordRange & PlaceRange)\r
-{\r
-    CPVT_WordPlace SecBeginPos = GetBeginWordPlace();\r
-    CPVT_WordPlace SecEndPos = GetEndWordPlace();\r
-    if (PlaceRange.BeginPos.WordCmp(SecBeginPos) >= 0) {\r
-        if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {\r
-            ClearMidWords(PlaceRange.BeginPos.nWordIndex, PlaceRange.EndPos.nWordIndex);\r
-        } else {\r
-            ClearRightWords(PlaceRange.BeginPos.nWordIndex);\r
-        }\r
-    } else if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {\r
-        ClearLeftWords(PlaceRange.EndPos.nWordIndex);\r
-    } else {\r
-        ResetWordArray();\r
-    }\r
-}\r
-void CSection::ClearWord(const CPVT_WordPlace & place)\r
-{\r
-    delete m_WordArray.GetAt(place.nWordIndex);\r
-    m_WordArray.RemoveAt(place.nWordIndex);\r
-}\r
-CTypeset::CTypeset(CSection * pSection) : m_pSection(pSection), m_pVT(pSection->m_pVT), m_rcRet(0.0f, 0.0f, 0.0f, 0.0f)\r
-{\r
-}\r
-CTypeset::~CTypeset()\r
-{\r
-}\r
-CPVT_FloatRect CTypeset::CharArray()\r
-{\r
-    ASSERT(m_pSection != NULL);\r
-    ASSERT(m_pVT != NULL);\r
-    FX_FLOAT fLineAscent = m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());\r
-    FX_FLOAT fLineDescent = m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());\r
-    m_rcRet.Default();\r
-    FX_FLOAT x = 0.0f, y = 0.0f;\r
-    FX_FLOAT fNextWidth;\r
-    FX_INT32 nStart = 0;\r
-    FX_FLOAT fNodeWidth = m_pVT->GetPlateWidth() / (m_pVT->m_nCharArray <= 0 ? 1 : m_pVT->m_nCharArray);\r
-    if (CLine * pLine = m_pSection->m_LineArray.GetAt(0)) {\r
-        x = 0.0f;\r
-        y +=  m_pVT->GetLineLeading(m_pSection->m_SecInfo);\r
-        y += fLineAscent;\r
-        nStart = 0;\r
-        switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {\r
-            case 0:\r
-                pLine->m_LineInfo.fLineX = fNodeWidth * PVT_HALF;\r
-                break;\r
-            case 1:\r
-                nStart = (m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize()) / 2;\r
-                pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;\r
-                break;\r
-            case 2:\r
-                nStart = m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize();\r
-                pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;\r
-                break;\r
-        }\r
-        for (FX_INT32 w = 0, sz = m_pSection->m_WordArray.GetSize(); w < sz; w++) {\r
-            if (w >= m_pVT->m_nCharArray) {\r
-                break;\r
-            }\r
-            fNextWidth = 0;\r
-            if (CPVT_WordInfo * pNextWord = (CPVT_WordInfo *)m_pSection->m_WordArray.GetAt(w + 1)) {\r
-                pNextWord->fWordTail = 0;\r
-                fNextWidth = m_pVT->GetWordWidth(*pNextWord);\r
-            }\r
-            if (CPVT_WordInfo * pWord = (CPVT_WordInfo *)m_pSection->m_WordArray.GetAt(w)) {\r
-                pWord->fWordTail = 0;\r
-                FX_FLOAT fWordWidth = m_pVT->GetWordWidth(*pWord);\r
-                FX_FLOAT fWordAscent = m_pVT->GetWordAscent(*pWord);\r
-                FX_FLOAT fWordDescent = m_pVT->GetWordDescent(*pWord);\r
-                x = (FX_FLOAT)(fNodeWidth * (w + nStart + 0.5) - fWordWidth * PVT_HALF);\r
-                pWord->fWordX = x;\r
-                pWord->fWordY = y;\r
-                if (w == 0) {\r
-                    pLine->m_LineInfo.fLineX = x;\r
-                }\r
-                if (w != m_pSection->m_WordArray.GetSize() - 1)\r
-                    pWord->fWordTail = (fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF > 0 ?\r
-                                        fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF : 0);\r
-                else {\r
-                    pWord->fWordTail = 0;\r
-                }\r
-                x += fWordWidth;\r
-                fLineAscent = FPDF_MAX(fLineAscent, fWordAscent);\r
-                fLineDescent = FPDF_MIN(fLineDescent, fWordDescent);\r
-            }\r
-        }\r
-        pLine->m_LineInfo.nBeginWordIndex = 0;\r
-        pLine->m_LineInfo.nEndWordIndex = m_pSection->m_WordArray.GetSize() - 1;\r
-        pLine->m_LineInfo.fLineY = y;\r
-        pLine->m_LineInfo.fLineWidth =         x - pLine->m_LineInfo.fLineX;\r
-        pLine->m_LineInfo.fLineAscent = fLineAscent;\r
-        pLine->m_LineInfo.fLineDescent = fLineDescent;\r
-        y += (-fLineDescent);\r
-    }\r
-    return m_rcRet = CPVT_FloatRect(0, 0, x, y);\r
-}\r
-CPVT_Size CTypeset::GetEditSize(FX_FLOAT fFontSize)\r
-{\r
-    ASSERT(m_pSection != NULL);\r
-    ASSERT(m_pVT != NULL);\r
-    SplitLines(FALSE, fFontSize);\r
-    return CPVT_Size(m_rcRet.Width(), m_rcRet.Height());\r
-}\r
-CPVT_FloatRect CTypeset::Typeset()\r
-{\r
-    ASSERT(m_pSection != NULL);\r
-    ASSERT(m_pVT != NULL);\r
-    m_pSection->m_LineArray.Empty();\r
-    SplitLines(TRUE, 0.0f);\r
-    m_pSection->m_LineArray.Clear();\r
-    OutputLines();\r
-    return m_rcRet;\r
-}\r
-static int special_chars[128] = {\r
-    0x0000, 0x000C, 0x0008, 0x000C, 0x0008, 0x0000, 0x0020, 0x0000,\r
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\r
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\r
-    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,\r
-    0x0000, 0x0008, 0x0008, 0x0000, 0x0010, 0x0000, 0x0000, 0x0028,\r
-    0x000C, 0x0008, 0x0000, 0x0000, 0x0028, 0x0028, 0x0028, 0x0028,\r
-    0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,\r
-    0x0002, 0x0002, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0008,\r
-    0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,\r
-    0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,\r
-    0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,\r
-    0x0001, 0x0001, 0x0001, 0x000C, 0x0000, 0x0008, 0x0000, 0x0000,\r
-    0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,\r
-    0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,\r
-    0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,\r
-    0x0001, 0x0001, 0x0001, 0x000C, 0x0000, 0x0008, 0x0000, 0x0000,\r
-};\r
-static FX_BOOL IsLatin(FX_WORD word)\r
-{\r
-    if (word <= 0x007F) {\r
-        if (special_chars[word] & 0x0001) {\r
-            return TRUE;\r
-        }\r
-    }\r
-    if ((word >= 0x00C0 && word <= 0x00FF) ||\r
-            (word >= 0x0100 && word <= 0x024F) ||\r
-            (word >= 0x1E00 && word <= 0x1EFF) ||\r
-            (word >= 0x2C60 && word <= 0x2C7F) ||\r
-            (word >= 0xA720 && word <= 0xA7FF) ||\r
-            (word >= 0xFF21 && word <= 0xFF3A) ||\r
-            (word >= 0xFF41 && word <= 0xFF5A)) {\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-static FX_BOOL IsDigit(FX_DWORD word)\r
-{\r
-    return (word >= 0x0030 && word <= 0x0039) ? TRUE : FALSE;\r
-}\r
-static FX_BOOL IsCJK(FX_DWORD word)\r
-{\r
-    if ((word >= 0x1100 && word <= 0x11FF) ||\r
-            (word >= 0x2E80 && word <= 0x2FFF) ||\r
-            (word >= 0x3040 && word <= 0x9FBF) ||\r
-            (word >= 0xAC00 && word <= 0xD7AF) ||\r
-            (word >= 0xF900 && word <= 0xFAFF) ||\r
-            (word >= 0xFE30 && word <= 0xFE4F) ||\r
-            (word >= 0x20000 && word <= 0x2A6DF) ||\r
-            (word >= 0x2F800 && word <= 0x2FA1F)) {\r
-        return TRUE;\r
-    }\r
-    if (word >= 0x3000 && word <= 0x303F) {\r
-        if (word == 0x3005 || word == 0x3006 || word == 0x3021 || word == 0x3022 ||\r
-                word == 0x3023 || word == 0x3024 || word == 0x3025 || word == 0x3026 ||\r
-                word == 0x3027 || word == 0x3028 || word == 0x3029 || word == 0x3031 ||\r
-                word == 0x3032 || word == 0x3033 || word == 0x3034 || word == 0x3035) {\r
-            return TRUE;\r
-        }\r
-        return FALSE;\r
-    }\r
-    if (word >= 0xFF66 && word <= 0xFF9D) {\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-static FX_BOOL IsPunctuation(FX_DWORD word)\r
-{\r
-    if (word <= 0x007F) {\r
-        if ((special_chars[word] >> 3) & 1) {\r
-            return TRUE;\r
-        }\r
-    } else if (word >= 0x0080 && word <= 0x00FF) {\r
-        if (word == 0x0082 || word == 0x0084 || word == 0x0085 || word == 0x0091 ||\r
-                word == 0x0092 || word == 0x0093 || word <= 0x0094 || word == 0x0096 ||\r
-                word == 0x00B4 || word == 0x00B8) {\r
-            return TRUE;\r
-        }\r
-    } else if (word >= 0x2000 && word <= 0x206F) {\r
-        if (word == 0x2010 || word == 0x2011 || word == 0x2012 || word == 0x2013 ||\r
-                word == 0x2018 || word == 0x2019 || word == 0x201A || word == 0x201B ||\r
-                word == 0x201C || word == 0x201D || word == 0x201E || word == 0x201F ||\r
-                word == 0x2032 || word == 0x2033 || word == 0x2034 || word == 0x2035 ||\r
-                word == 0x2036 || word == 0x2037 || word == 0x203C || word == 0x203D ||\r
-                word == 0x203E || word == 0x2044) {\r
-            return TRUE;\r
-        }\r
-    } else if (word >= 0x3000 && word <= 0x303F) {\r
-        if (word == 0x3001 || word == 0x3002 || word == 0x3003 || word == 0x3005 ||\r
-                word == 0x3009 || word == 0x300A || word == 0x300B || word == 0x300C ||\r
-                word == 0x300D || word == 0x300F || word == 0x300E || word == 0x3010 ||\r
-                word == 0x3011 || word == 0x3014 || word == 0x3015 || word == 0x3016 ||\r
-                word == 0x3017 || word == 0x3018 || word == 0x3019 || word == 0x301A ||\r
-                word == 0x301B || word == 0x301D || word == 0x301E || word == 0x301F) {\r
-            return TRUE;\r
-        }\r
-    } else if (word >= 0xFE50 && word <= 0xFE6F) {\r
-        if ((word >= 0xFE50 && word <= 0xFE5E) || word == 0xFE63) {\r
-            return TRUE;\r
-        }\r
-    } else if (word >= 0xFF00 && word <= 0xFFEF) {\r
-        if (word == 0xFF01 || word == 0xFF02 || word == 0xFF07 || word == 0xFF08 ||\r
-                word == 0xFF09 || word == 0xFF0C || word == 0xFF0E || word == 0xFF0F ||\r
-                word == 0xFF1A || word == 0xFF1B || word == 0xFF1F || word == 0xFF3B ||\r
-                word == 0xFF3D || word == 0xFF40 || word == 0xFF5B || word == 0xFF5C ||\r
-                word == 0xFF5D || word == 0xFF61 || word == 0xFF62 || word == 0xFF63 ||\r
-                word == 0xFF64 || word == 0xFF65 || word == 0xFF9E || word == 0xFF9F) {\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-static FX_BOOL IsConnectiveSymbol(FX_DWORD word)\r
-{\r
-    if (word <= 0x007F) {\r
-        if ((special_chars[word] >> 5) & 1) {\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-static FX_BOOL IsOpenStylePunctuation(FX_DWORD word)\r
-{\r
-    if (word <= 0x007F) {\r
-        if ((special_chars[word] >> 2) & 1) {\r
-            return TRUE;\r
-        }\r
-    } else if (word == 0x300A || word == 0x300C || word == 0x300E || word == 0x3010 ||\r
-               word == 0x3014 || word == 0x3016 || word == 0x3018 || word == 0x301A ||\r
-               word == 0xFF08 || word == 0xFF3B || word == 0xFF5B || word == 0xFF62) {\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-static FX_BOOL IsCurrencySymbol(FX_WORD word)\r
-{\r
-    if (word == 0x0024 || word == 0x0080 || word == 0x00A2 || word == 0x00A3 ||\r
-            word == 0x00A4 || word == 0x00A5 || (word >= 0x20A0 && word <= 0x20CF) ||\r
-            word == 0xFE69 || word == 0xFF04 || word == 0xFFE0 || word == 0xFFE1 ||\r
-            word == 0xFFE5 || word == 0xFFE6) {\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-static FX_BOOL IsPrefixSymbol(FX_WORD word)\r
-{\r
-    if (IsCurrencySymbol(word)) {\r
-        return TRUE;\r
-    }\r
-    if (word == 0x2116) {\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-static FX_BOOL IsSpace(FX_WORD word)\r
-{\r
-    return (word == 0x0020 || word == 0x3000) ? TRUE : FALSE;\r
-}\r
-static FX_BOOL NeedDivision(FX_WORD prevWord, FX_WORD curWord)\r
-{\r
-    if ((IsLatin(prevWord) || IsDigit(prevWord)) && (IsLatin(curWord) || IsDigit(curWord))) {\r
-        return FALSE;\r
-    } else if (IsSpace(curWord) || IsPunctuation(curWord)) {\r
-        return FALSE;\r
-    } else if (IsConnectiveSymbol(prevWord) || IsConnectiveSymbol(curWord)) {\r
-        return FALSE;\r
-    } else if (IsSpace(prevWord) || IsPunctuation(prevWord)) {\r
-        return TRUE;\r
-    } else if (IsPrefixSymbol(prevWord)) {\r
-        return FALSE;\r
-    } else if (IsPrefixSymbol(curWord) || IsCJK(curWord)) {\r
-        return TRUE;\r
-    } else if (IsCJK(prevWord)) {\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-void CTypeset::SplitLines(FX_BOOL bTypeset, FX_FLOAT fFontSize)\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    ASSERT(m_pSection != NULL);\r
-    FX_INT32 nLineHead = 0;\r
-    FX_INT32 nLineTail = 0;\r
-    FX_FLOAT fMaxX = 0.0f, fMaxY = 0.0f;\r
-    FX_FLOAT fLineWidth = 0.0f, fBackupLineWidth = 0.0f;\r
-    FX_FLOAT fLineAscent = 0.0f, fBackupLineAscent = 0.0f;\r
-    FX_FLOAT fLineDescent = 0.0f, fBackupLineDescent = 0.0f;\r
-    FX_INT32 nWordStartPos = 0;\r
-    FX_BOOL bFullWord = FALSE;\r
-    FX_INT32 nLineFullWordIndex = 0;\r
-    FX_INT32 nCharIndex = 0;\r
-    CPVT_LineInfo line;\r
-    FX_FLOAT fWordWidth = 0;\r
-    FX_FLOAT fTypesetWidth = FPDF_MAX(m_pVT->GetPlateWidth() - m_pVT->GetLineIndent(m_pSection->m_SecInfo), 0.0f);\r
-    FX_INT32 nTotalWords = m_pSection->m_WordArray.GetSize();\r
-    FX_BOOL bOpened = FALSE;\r
-    if (nTotalWords > 0) {\r
-        FX_INT32 i = 0;\r
-        while (i < nTotalWords) {\r
-            CPVT_WordInfo * pWord = m_pSection->m_WordArray.GetAt(i);\r
-            CPVT_WordInfo* pOldWord = pWord;\r
-            if (i > 0) {\r
-                pOldWord = m_pSection->m_WordArray.GetAt(i - 1);\r
-            }\r
-            if (pWord) {\r
-                if (bTypeset) {\r
-                    fLineAscent = FPDF_MAX(fLineAscent, m_pVT->GetWordAscent(*pWord, TRUE));\r
-                    fLineDescent = FPDF_MIN(fLineDescent, m_pVT->GetWordDescent(*pWord, TRUE));\r
-                    fWordWidth = m_pVT->GetWordWidth(*pWord);\r
-                } else {\r
-                    fLineAscent = FPDF_MAX(fLineAscent, m_pVT->GetWordAscent(*pWord, fFontSize));\r
-                    fLineDescent = FPDF_MIN(fLineDescent, m_pVT->GetWordDescent(*pWord, fFontSize));\r
-                    fWordWidth = m_pVT->GetWordWidth(pWord->nFontIndex,\r
-                                                     pWord->Word,\r
-                                                     m_pVT->m_wSubWord,\r
-                                                     m_pVT->m_fCharSpace,\r
-                                                     m_pVT->m_nHorzScale,\r
-                                                     fFontSize,\r
-                                                     pWord->fWordTail,\r
-                                                     0);\r
-                }\r
-                if (!bOpened) {\r
-                    if (IsOpenStylePunctuation(pWord->Word)) {\r
-                        bOpened = TRUE;\r
-                        bFullWord = TRUE;\r
-                    } else if (pOldWord != NULL) {\r
-                        if (NeedDivision(pOldWord->Word, pWord->Word)) {\r
-                            bFullWord = TRUE;\r
-                        }\r
-                    }\r
-                } else {\r
-                    if (!IsSpace(pWord->Word) && !IsOpenStylePunctuation(pWord->Word)) {\r
-                        bOpened = FALSE;\r
-                    }\r
-                }\r
-                if (bFullWord) {\r
-                    bFullWord = FALSE;\r
-                    if (nCharIndex > 0) {\r
-                        nLineFullWordIndex ++;\r
-                    }\r
-                    nWordStartPos = i;\r
-                    fBackupLineWidth = fLineWidth;\r
-                    fBackupLineAscent = fLineAscent;\r
-                    fBackupLineDescent = fLineDescent;\r
-                }\r
-                nCharIndex++;\r
-            }\r
-            if (m_pVT->m_bLimitWidth && fTypesetWidth > 0 &&\r
-                    fLineWidth + fWordWidth > fTypesetWidth) {\r
-                if (nLineFullWordIndex > 0) {\r
-                    i = nWordStartPos;\r
-                    fLineWidth = fBackupLineWidth;\r
-                    fLineAscent = fBackupLineAscent;\r
-                    fLineDescent = fBackupLineDescent;\r
-                }\r
-                if (nCharIndex == 1) {\r
-                    fLineWidth =  fWordWidth;\r
-                    i++;\r
-                }\r
-                nLineTail = i - 1;\r
-                if (bTypeset) {\r
-                    line.nBeginWordIndex = nLineHead;\r
-                    line.nEndWordIndex = nLineTail;\r
-                    line.nTotalWord = nLineTail - nLineHead + 1;\r
-                    line.fLineWidth = fLineWidth;\r
-                    line.fLineAscent = fLineAscent;\r
-                    line.fLineDescent = fLineDescent;\r
-                    m_pSection->AddLine(line);\r
-                }\r
-                fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo));\r
-                fMaxY += (-fLineDescent);\r
-                fMaxX = FPDF_MAX(fLineWidth, fMaxX);\r
-                nLineHead = i;\r
-                fLineWidth = 0.0f;\r
-                fLineAscent = 0.0f;\r
-                fLineDescent = 0.0f;\r
-                nCharIndex = 0;\r
-                nLineFullWordIndex = 0;\r
-                bFullWord = FALSE;\r
-            } else {\r
-                fLineWidth += fWordWidth;\r
-                i++;\r
-            }\r
-        }\r
-        if (nLineHead <= nTotalWords - 1) {\r
-            nLineTail = nTotalWords - 1;\r
-            if (bTypeset) {\r
-                line.nBeginWordIndex = nLineHead;\r
-                line.nEndWordIndex = nLineTail;\r
-                line.nTotalWord = nLineTail - nLineHead + 1;\r
-                line.fLineWidth = fLineWidth;\r
-                line.fLineAscent = fLineAscent;\r
-                line.fLineDescent = fLineDescent;\r
-                m_pSection->AddLine(line);\r
-            }\r
-            fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo));\r
-            fMaxY += (-fLineDescent);\r
-            fMaxX = FPDF_MAX(fLineWidth, fMaxX);\r
-        }\r
-    } else {\r
-        if (bTypeset) {\r
-            fLineAscent = m_pVT->GetLineAscent(m_pSection->m_SecInfo);\r
-            fLineDescent = m_pVT->GetLineDescent(m_pSection->m_SecInfo);\r
-        } else {\r
-            fLineAscent = m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), fFontSize);\r
-            fLineDescent = m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), fFontSize);\r
-        }\r
-        if (bTypeset) {\r
-            line.nBeginWordIndex = -1;\r
-            line.nEndWordIndex = -1;\r
-            line.nTotalWord = 0;\r
-            line.fLineWidth = 0;\r
-            line.fLineAscent = fLineAscent;\r
-            line.fLineDescent = fLineDescent;\r
-            m_pSection->AddLine(line);\r
-        }\r
-        fMaxY += (m_pVT->GetLineLeading(m_pSection->m_SecInfo) + fLineAscent + (-fLineDescent));\r
-    }\r
-    m_rcRet = CPVT_FloatRect(0, 0, fMaxX, fMaxY);\r
-}\r
-void CTypeset::OutputLines()\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    ASSERT(m_pSection != NULL);\r
-    FX_FLOAT fMinX = 0.0f, fMinY = 0.0f, fMaxX = 0.0f, fMaxY = 0.0f;\r
-    FX_FLOAT fPosX = 0.0f, fPosY = 0.0f;\r
-    FX_FLOAT fLineIndent = m_pVT->GetLineIndent(m_pSection->m_SecInfo);\r
-    FX_FLOAT fTypesetWidth = FPDF_MAX(m_pVT->GetPlateWidth() - fLineIndent, 0.0f);\r
-    switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {\r
-        default:\r
-        case 0:\r
-            fMinX = 0.0f;\r
-            break;\r
-        case 1:\r
-            fMinX = (fTypesetWidth - m_rcRet.Width())  * PVT_HALF;\r
-            break;\r
-        case 2:\r
-            fMinX = fTypesetWidth - m_rcRet.Width();\r
-            break;\r
-    }\r
-    fMaxX = fMinX + m_rcRet.Width();\r
-    fMinY = 0.0f;\r
-    fMaxY = m_rcRet.Height();\r
-    FX_INT32 nTotalLines = m_pSection->m_LineArray.GetSize();\r
-    if (nTotalLines > 0) {\r
-        m_pSection->m_SecInfo.nTotalLine = nTotalLines;\r
-        for (FX_INT32 l = 0; l < nTotalLines; l++) {\r
-            if (CLine * pLine = m_pSection->m_LineArray.GetAt(l)) {\r
-                switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {\r
-                    default:\r
-                    case 0:\r
-                        fPosX = 0;\r
-                        break;\r
-                    case 1:\r
-                        fPosX = (fTypesetWidth - pLine->m_LineInfo.fLineWidth) * PVT_HALF;\r
-                        break;\r
-                    case 2:\r
-                        fPosX = fTypesetWidth - pLine->m_LineInfo.fLineWidth;\r
-                        break;\r
-                }\r
-                fPosX += fLineIndent;\r
-                fPosY += m_pVT->GetLineLeading(m_pSection->m_SecInfo);\r
-                fPosY += pLine->m_LineInfo.fLineAscent;\r
-                pLine->m_LineInfo.fLineX = fPosX - fMinX;\r
-                pLine->m_LineInfo.fLineY = fPosY - fMinY;\r
-                for (FX_INT32 w = pLine->m_LineInfo.nBeginWordIndex; w <= pLine->m_LineInfo.nEndWordIndex; w++) {\r
-                    if (CPVT_WordInfo * pWord = m_pSection->m_WordArray.GetAt(w)) {\r
-                        pWord->fWordX = fPosX - fMinX;\r
-                        if (pWord->pWordProps) {\r
-                            switch (pWord->pWordProps->nScriptType) {\r
-                                default:\r
-                                case PVTWORD_SCRIPT_NORMAL:\r
-                                    pWord->fWordY = fPosY - fMinY;\r
-                                    break;\r
-                                case PVTWORD_SCRIPT_SUPER:\r
-                                    pWord->fWordY = fPosY - m_pVT->GetWordAscent(*pWord) - fMinY;\r
-                                    break;\r
-                                case PVTWORD_SCRIPT_SUB:\r
-                                    pWord->fWordY = fPosY - m_pVT->GetWordDescent(*pWord) - fMinY;\r
-                                    break;\r
-                            }\r
-                        } else {\r
-                            pWord->fWordY = fPosY - fMinY;\r
-                        }\r
-                        fPosX += m_pVT->GetWordWidth(*pWord);\r
-                    }\r
-                }\r
-                fPosY += (-pLine->m_LineInfo.fLineDescent);\r
-            }\r
-        }\r
-    }\r
-    m_rcRet = CPVT_FloatRect(fMinX, fMinY, fMaxX, fMaxY);\r
-}\r
-CPDF_VariableText::CPDF_VariableText() :\r
-    m_pVTProvider(NULL),\r
-    m_pVTIterator(NULL),\r
-    m_bInitial(FALSE),\r
-    m_bRichText(FALSE),\r
-    m_bMultiLine(FALSE),\r
-    m_bLimitWidth(FALSE),\r
-    m_bAutoFontSize(FALSE),\r
-    m_nLimitChar(0),\r
-    m_nCharArray(0),\r
-    m_nAlignment(0),\r
-    m_fCharSpace(0.0f),\r
-    m_fWordSpace(0.0f),\r
-    m_fFontSize(0.0f),\r
-    m_nHorzScale(100),\r
-    m_wSubWord(0),\r
-    m_fLineLeading(0.0f)\r
-{\r
-}\r
-CPDF_VariableText::~CPDF_VariableText()\r
-{\r
-    if (m_pVTIterator) {\r
-        delete m_pVTIterator;\r
-        m_pVTIterator = NULL;\r
-    }\r
-    ResetAll();\r
-}\r
-void CPDF_VariableText::Initialize()\r
-{\r
-    if (!m_bInitial) {\r
-        CPVT_SectionInfo secinfo;\r
-        if (m_bRichText) {\r
-            secinfo.pSecProps = FX_NEW CPVT_SecProps(0.0f, 0.0f, 0);\r
-            secinfo.pWordProps = FX_NEW CPVT_WordProps(GetDefaultFontIndex(), PVT_DEFAULT_FONTSIZE, 0, 0, 0);\r
-        }\r
-        CPVT_WordPlace place;\r
-        place.nSecIndex = 0;\r
-        AddSection(place, secinfo);\r
-        CPVT_LineInfo lineinfo;\r
-        lineinfo.fLineAscent = GetFontAscent(GetDefaultFontIndex(), GetFontSize());\r
-        lineinfo.fLineDescent = GetFontDescent(GetDefaultFontIndex(), GetFontSize());\r
-        AddLine(place, lineinfo);\r
-        if (CSection * pSection = m_SectionArray.GetAt(0)) {\r
-            pSection->ResetLinePlace();\r
-        }\r
-        m_bInitial = TRUE;\r
-    }\r
-}\r
-void CPDF_VariableText::ResetAll()\r
-{\r
-    m_bInitial = FALSE;\r
-    ResetSectionArray();\r
-}\r
-CPVT_WordPlace CPDF_VariableText::InsertWord(const CPVT_WordPlace & place, FX_WORD word, FX_INT32 charset,\r
-        const CPVT_WordProps * pWordProps)\r
-{\r
-    FX_INT32 nTotlaWords = this->GetTotalWords();\r
-    if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {\r
-        return place;\r
-    }\r
-    if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {\r
-        return place;\r
-    }\r
-    CPVT_WordPlace newplace = place;\r
-    newplace.nWordIndex ++;\r
-    if (m_bRichText) {\r
-        CPVT_WordProps * pNewProps = pWordProps ? FX_NEW CPVT_WordProps(*pWordProps) : FX_NEW CPVT_WordProps();\r
-        if (pNewProps) {\r
-            pNewProps->nFontIndex = GetWordFontIndex(word, charset, pWordProps->nFontIndex);\r
-            return AddWord(newplace, CPVT_WordInfo(word, charset, -1, pNewProps));\r
-        }\r
-    } else {\r
-        FX_INT32 nFontIndex = GetSubWord() > 0 ? GetDefaultFontIndex() : GetWordFontIndex(word, charset, GetDefaultFontIndex());\r
-        return AddWord(newplace, CPVT_WordInfo(word, charset, nFontIndex, NULL));\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::InsertSection(const CPVT_WordPlace & place, const CPVT_SecProps * pSecProps,\r
-        const CPVT_WordProps * pWordProps)\r
-{\r
-    FX_INT32 nTotlaWords = this->GetTotalWords();\r
-    if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {\r
-        return place;\r
-    }\r
-    if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {\r
-        return place;\r
-    }\r
-    if (!m_bMultiLine) {\r
-        return place;\r
-    }\r
-    CPVT_WordPlace wordplace = place;\r
-    UpdateWordPlace(wordplace);\r
-    CPVT_WordPlace newplace = place;\r
-    if (CSection * pSection = m_SectionArray.GetAt(wordplace.nSecIndex)) {\r
-        CPVT_WordPlace NewPlace(wordplace.nSecIndex + 1, 0, -1);\r
-        CPVT_SectionInfo secinfo;\r
-        if (m_bRichText) {\r
-            if (pSecProps) {\r
-                secinfo.pSecProps = FX_NEW CPVT_SecProps(*pSecProps);\r
-            }\r
-            if (pWordProps) {\r
-                secinfo.pWordProps = FX_NEW CPVT_WordProps(*pWordProps);\r
-            }\r
-        }\r
-        AddSection(NewPlace, secinfo);\r
-        newplace = NewPlace;\r
-        if (CSection * pNewSection = m_SectionArray.GetAt(NewPlace.nSecIndex)) {\r
-            for (FX_INT32 w = wordplace.nWordIndex + 1, sz = pSection->m_WordArray.GetSize(); w < sz; w++) {\r
-                if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(w)) {\r
-                    NewPlace.nWordIndex++;\r
-                    pNewSection->AddWord(NewPlace, *pWord);\r
-                }\r
-            }\r
-        }\r
-        ClearSectionRightWords(wordplace);\r
-    }\r
-    return newplace;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::InsertText(const CPVT_WordPlace & place, FX_LPCWSTR text, FX_INT32 charset,\r
-        const CPVT_SecProps * pSecProps, const CPVT_WordProps * pProps)\r
-{\r
-    CFX_WideString swText = text;\r
-    CPVT_WordPlace wp = place;\r
-    for (FX_INT32 i = 0, sz = swText.GetLength(); i < sz; i++) {\r
-        CPVT_WordPlace oldwp = wp;\r
-        FX_WORD word = swText.GetAt(i);\r
-        switch (word) {\r
-            case 0x0D:\r
-                if (m_bMultiLine) {\r
-                    if (swText.GetAt(i + 1) == 0x0A) {\r
-                        i += 1;\r
-                    }\r
-                    wp = InsertSection(wp, pSecProps, pProps);\r
-                }\r
-                break;\r
-            case 0x0A:\r
-                if (m_bMultiLine) {\r
-                    if (swText.GetAt(i + 1) == 0x0D) {\r
-                        i += 1;\r
-                    }\r
-                    wp = InsertSection(wp, pSecProps, pProps);\r
-                }\r
-                break;\r
-            case 0x09:\r
-                word = 0x20;\r
-            default:\r
-                wp = InsertWord(wp, word, charset, pProps);\r
-                break;\r
-        }\r
-        if (wp == oldwp) {\r
-            break;\r
-        }\r
-    }\r
-    return wp;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::DeleteWords(const CPVT_WordRange & PlaceRange)\r
-{\r
-    FX_BOOL bLastSecPos = FALSE;\r
-    if (CSection * pSection = m_SectionArray.GetAt(PlaceRange.EndPos.nSecIndex)) {\r
-        bLastSecPos = (PlaceRange.EndPos == pSection->GetEndWordPlace());\r
-    }\r
-    ClearWords(PlaceRange);\r
-    if (PlaceRange.BeginPos.nSecIndex != PlaceRange.EndPos.nSecIndex) {\r
-        ClearEmptySections(PlaceRange);\r
-        if (!bLastSecPos) {\r
-            LinkLatterSection(PlaceRange.BeginPos);\r
-        }\r
-    }\r
-    return PlaceRange.BeginPos;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::DeleteWord(const CPVT_WordPlace & place)\r
-{\r
-    return ClearRightWord(AjustLineHeader(place, TRUE));\r
-}\r
-CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace & place)\r
-{\r
-    return ClearLeftWord(AjustLineHeader(place, TRUE));\r
-}\r
-void CPDF_VariableText::SetText(FX_LPCWSTR text, FX_INT32 charset, const CPVT_SecProps * pSecProps,\r
-                                const CPVT_WordProps * pWordProps)\r
-{\r
-    DeleteWords(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));\r
-    CFX_WideString swText = text;\r
-    CPVT_WordPlace     wp(0, 0, -1);\r
-    CPVT_SectionInfo secinfo;\r
-    if (m_bRichText) {\r
-        if (pSecProps) {\r
-            secinfo.pSecProps = FX_NEW CPVT_SecProps(*pSecProps);\r
-        }\r
-        if (pWordProps) {\r
-            secinfo.pWordProps = FX_NEW CPVT_WordProps(*pWordProps);\r
-        }\r
-    }\r
-    if (CSection * pSection = m_SectionArray.GetAt(0)) {\r
-        pSection->m_SecInfo = secinfo;\r
-    }\r
-    FX_INT32 nCharCount = 0;\r
-    for (FX_INT32 i = 0, sz = swText.GetLength(); i < sz; i++) {\r
-        if (m_nLimitChar > 0 && nCharCount >= m_nLimitChar) {\r
-            break;\r
-        }\r
-        if (m_nCharArray > 0 && nCharCount >= m_nCharArray) {\r
-            break;\r
-        }\r
-        FX_WORD word = swText.GetAt(i);\r
-        switch (word) {\r
-            case 0x0D:\r
-                if (m_bMultiLine) {\r
-                    if (swText.GetAt(i + 1) == 0x0A) {\r
-                        i += 1;\r
-                    }\r
-                    wp.nSecIndex ++;\r
-                    wp.nLineIndex = 0;\r
-                    wp.nWordIndex = -1;\r
-                    AddSection(wp, secinfo);\r
-                }\r
-                break;\r
-            case 0x0A:\r
-                if (m_bMultiLine) {\r
-                    if (swText.GetAt(i + 1) == 0x0D) {\r
-                        i += 1;\r
-                    }\r
-                    wp.nSecIndex ++;\r
-                    wp.nLineIndex = 0;\r
-                    wp.nWordIndex = -1;\r
-                    AddSection(wp, secinfo);\r
-                }\r
-                break;\r
-            case 0x09:\r
-                word = 0x20;\r
-            default:\r
-                wp = InsertWord(wp, word, charset, pWordProps);\r
-                break;\r
-        }\r
-        nCharCount++;\r
-    }\r
-}\r
-void CPDF_VariableText::UpdateWordPlace(CPVT_WordPlace & place) const\r
-{\r
-    if (place.nSecIndex < 0) {\r
-        place = GetBeginWordPlace();\r
-    }\r
-    if (place.nSecIndex >= m_SectionArray.GetSize()) {\r
-        place = GetEndWordPlace();\r
-    }\r
-    place = AjustLineHeader(place, TRUE);\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        pSection->UpdateWordPlace(place);\r
-    }\r
-}\r
-FX_INT32 CPDF_VariableText::WordPlaceToWordIndex(const CPVT_WordPlace & place) const\r
-{\r
-    CPVT_WordPlace newplace = place;\r
-    UpdateWordPlace(newplace);\r
-    FX_INT32 nIndex = 0;\r
-    FX_INT32 i = 0;\r
-    FX_INT32 sz = 0;\r
-    for (i = 0, sz = m_SectionArray.GetSize(); i < sz && i < newplace.nSecIndex; i++) {\r
-        if (CSection * pSection = m_SectionArray.GetAt(i)) {\r
-            nIndex += pSection->m_WordArray.GetSize();\r
-            if (i != m_SectionArray.GetSize() - 1) {\r
-                nIndex += PVT_RETURN_LENGTH;\r
-            }\r
-        }\r
-    }\r
-    if (i >= 0 && i < m_SectionArray.GetSize()) {\r
-        nIndex += newplace.nWordIndex + PVT_RETURN_LENGTH;\r
-    }\r
-    return nIndex;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::WordIndexToWordPlace(FX_INT32 index) const\r
-{\r
-    CPVT_WordPlace place = GetBeginWordPlace();\r
-    FX_INT32 nOldIndex = 0 , nIndex = 0;\r
-    FX_BOOL bFind = FALSE;\r
-    for (FX_INT32 i = 0, sz = m_SectionArray.GetSize(); i < sz; i++) {\r
-        if (CSection * pSection = m_SectionArray.GetAt(i)) {\r
-            nIndex += pSection->m_WordArray.GetSize();\r
-            if (nIndex == index) {\r
-                place = pSection->GetEndWordPlace();\r
-                bFind = TRUE;\r
-                break;\r
-            } else if (nIndex > index) {\r
-                place.nSecIndex = i;\r
-                place.nWordIndex = index - nOldIndex - 1;\r
-                pSection->UpdateWordPlace(place);\r
-                bFind = TRUE;\r
-                break;\r
-            }\r
-            if (i != m_SectionArray.GetSize() - 1) {\r
-                nIndex += PVT_RETURN_LENGTH;\r
-            }\r
-            nOldIndex = nIndex;\r
-        }\r
-    }\r
-    if (!bFind) {\r
-        place = GetEndWordPlace();\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::GetBeginWordPlace() const\r
-{\r
-    return m_bInitial ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace();\r
-}\r
-CPVT_WordPlace CPDF_VariableText::GetEndWordPlace() const\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(m_SectionArray.GetSize() - 1)) {\r
-        return pSection->GetEndWordPlace();\r
-    }\r
-    return CPVT_WordPlace();\r
-}\r
-CPVT_WordPlace CPDF_VariableText::GetPrevWordPlace(const CPVT_WordPlace & place) const\r
-{\r
-    if( place.nSecIndex < 0) {\r
-        return GetBeginWordPlace();\r
-    }\r
-    if (place.nSecIndex >= m_SectionArray.GetSize()) {\r
-        return GetEndWordPlace();\r
-    }\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        if (place.WordCmp(pSection->GetBeginWordPlace()) <= 0) {\r
-            if (CSection * pPrevSection = m_SectionArray.GetAt(place.nSecIndex - 1)) {\r
-                return pPrevSection->GetEndWordPlace();\r
-            } else {\r
-                return GetBeginWordPlace();\r
-            }\r
-        } else {\r
-            return pSection->GetPrevWordPlace(place);\r
-        }\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::GetNextWordPlace(const CPVT_WordPlace & place) const\r
-{\r
-    if (place.nSecIndex < 0) {\r
-        return GetBeginWordPlace();\r
-    }\r
-    if (place.nSecIndex >= m_SectionArray.GetSize()) {\r
-        return GetEndWordPlace();\r
-    }\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        if (place.WordCmp(pSection->GetEndWordPlace()) >= 0) {\r
-            if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {\r
-                return pNextSection->GetBeginWordPlace();\r
-            } else {\r
-                return GetEndWordPlace();\r
-            }\r
-        } else {\r
-            return pSection->GetNextWordPlace(place);\r
-        }\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::SearchWordPlace(const CPDF_Point & point) const\r
-{\r
-    CPDF_Point pt = OutToIn(point);\r
-    CPVT_WordPlace place = GetBeginWordPlace();\r
-    FX_INT32 nLeft = 0;\r
-    FX_INT32 nRight = m_SectionArray.GetSize() - 1;\r
-    FX_INT32 nMid = m_SectionArray.GetSize() / 2;\r
-    FX_BOOL bUp = TRUE;\r
-    FX_BOOL bDown = TRUE;\r
-    while (nLeft <= nRight) {\r
-        if (CSection * pSection = m_SectionArray.GetAt(nMid)) {\r
-            if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.top)) {\r
-                bUp = FALSE;\r
-            }\r
-            if (IsFloatBigger(pSection->m_SecInfo.rcSection.bottom, pt.y)) {\r
-                bDown = FALSE;\r
-            }\r
-            if (IsFloatSmaller(pt.y, pSection->m_SecInfo.rcSection.top)) {\r
-                nRight = nMid - 1;\r
-                nMid = (nLeft + nRight) / 2;\r
-                continue;\r
-            } else if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.bottom)) {\r
-                nLeft = nMid + 1;\r
-                nMid = (nLeft + nRight) / 2;\r
-                continue;\r
-            } else {\r
-                place = pSection->SearchWordPlace(\r
-                            CPDF_Point(pt.x - pSection->m_SecInfo.rcSection.left, pt.y - pSection->m_SecInfo.rcSection.top)\r
-                        );\r
-                place.nSecIndex = nMid;\r
-                return place;\r
-            }\r
-        } else {\r
-            break;\r
-        }\r
-    }\r
-    if (bUp) {\r
-        place = GetBeginWordPlace();\r
-    }\r
-    if (bDown) {\r
-        place = GetEndWordPlace();\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::GetUpWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        CPVT_WordPlace temp =  place;\r
-        CPDF_Point pt = OutToIn(point);\r
-        if (temp.nLineIndex-- > 0) {\r
-            return pSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);\r
-        } else {\r
-            if (temp.nSecIndex-- > 0) {\r
-                if (CSection * pLastSection = m_SectionArray.GetAt(temp.nSecIndex)) {\r
-                    temp.nLineIndex = pLastSection->m_LineArray.GetSize() - 1;\r
-                    return pLastSection->SearchWordPlace(pt.x - pLastSection->m_SecInfo.rcSection.left, temp);\r
-                }\r
-            }\r
-        }\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::GetDownWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        CPVT_WordPlace temp =  place;\r
-        CPDF_Point pt = OutToIn(point);\r
-        if (temp.nLineIndex++ < pSection->m_LineArray.GetSize() - 1) {\r
-            return pSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);\r
-        } else {\r
-            if (temp.nSecIndex++ < m_SectionArray.GetSize() - 1) {\r
-                if (CSection * pNextSection = m_SectionArray.GetAt(temp.nSecIndex)) {\r
-                    temp.nLineIndex = 0;\r
-                    return pNextSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);\r
-                }\r
-            }\r
-        }\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace(const CPVT_WordPlace & place) const\r
-{\r
-    return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);\r
-}\r
-CPVT_WordPlace CPDF_VariableText::GetLineEndPlace(const CPVT_WordPlace & place) const\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex))\r
-        if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {\r
-            return pLine->GetEndWordPlace();\r
-        }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace(const CPVT_WordPlace & place) const\r
-{\r
-    return CPVT_WordPlace(place.nSecIndex, 0, -1);\r
-}\r
-CPVT_WordPlace CPDF_VariableText::GetSectionEndPlace(const CPVT_WordPlace & place) const\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        return pSection->GetEndWordPlace();\r
-    }\r
-    return place;\r
-}\r
-FX_INT32 CPDF_VariableText::GetTotalWords() const\r
-{\r
-    FX_INT32 nTotal = 0;\r
-    for (FX_INT32 i = 0, sz = m_SectionArray.GetSize(); i < sz; i++)\r
-        if (CSection * pSection = m_SectionArray.GetAt(i)) {\r
-            nTotal += (pSection->m_WordArray.GetSize() + PVT_RETURN_LENGTH);\r
-        }\r
-    return nTotal - PVT_RETURN_LENGTH;\r
-}\r
-void CPDF_VariableText::ResetSectionArray()\r
-{\r
-    for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {\r
-        delete m_SectionArray.GetAt(s);\r
-    }\r
-    m_SectionArray.RemoveAll();\r
-}\r
-CPVT_WordPlace CPDF_VariableText::AddSection(const CPVT_WordPlace & place, const CPVT_SectionInfo & secinfo)\r
-{\r
-    if (IsValid() && !m_bMultiLine) {\r
-        return place;\r
-    }\r
-    FX_INT32 nSecIndex = FPDF_MAX(FPDF_MIN(place.nSecIndex, m_SectionArray.GetSize()), 0);\r
-    CSection * pSection = FX_NEW CSection(this);\r
-    if (!pSection) {\r
-        return place;\r
-    }\r
-    pSection->m_SecInfo = secinfo;\r
-    pSection->SecPlace.nSecIndex = nSecIndex;\r
-    if (nSecIndex == m_SectionArray.GetSize()) {\r
-        m_SectionArray.Add(pSection);\r
-    } else {\r
-        m_SectionArray.InsertAt(nSecIndex, pSection);\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::AddLine(const CPVT_WordPlace & place, const CPVT_LineInfo & lineinfo)\r
-{\r
-    if (m_SectionArray.IsEmpty()) {\r
-        return place;\r
-    }\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        return pSection->AddLine(lineinfo);\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)\r
-{\r
-    if (m_SectionArray.GetSize() <= 0) {\r
-        return place;\r
-    }\r
-    CPVT_WordPlace newplace = place;\r
-    newplace.nSecIndex = FPDF_MAX(FPDF_MIN(newplace.nSecIndex, m_SectionArray.GetSize() - 1), 0);\r
-    if (CSection * pSection = m_SectionArray.GetAt(newplace.nSecIndex)) {\r
-        return pSection->AddWord(newplace, wordinfo);\r
-    }\r
-    return place;\r
-}\r
-FX_BOOL CPDF_VariableText::GetWordInfo(const CPVT_WordPlace & place, CPVT_WordInfo & wordinfo)\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {\r
-            wordinfo = *pWord;\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL CPDF_VariableText::SetWordInfo(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {\r
-            *pWord = wordinfo;\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL CPDF_VariableText::GetLineInfo(const CPVT_WordPlace & place, CPVT_LineInfo & lineinfo)\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {\r
-            lineinfo = pLine->m_LineInfo;\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL CPDF_VariableText::GetSectionInfo(const CPVT_WordPlace & place, CPVT_SectionInfo & secinfo)\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        secinfo = pSection->m_SecInfo;\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-CPDF_Rect CPDF_VariableText::GetContentRect() const\r
-{\r
-    return InToOut(CPDF_EditContainer::GetContentRect());\r
-}\r
-FX_FLOAT CPDF_VariableText::GetWordFontSize(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)\r
-{\r
-    return m_bRichText && WordInfo.pWordProps ? (WordInfo.pWordProps->nScriptType == PVTWORD_SCRIPT_NORMAL || bFactFontSize ? WordInfo.pWordProps->fFontSize : WordInfo.pWordProps->fFontSize * PVT_HALF) : GetFontSize();\r
-}\r
-FX_INT32 CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo & WordInfo)\r
-{\r
-    return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nFontIndex : WordInfo.nFontIndex;\r
-}\r
-FX_FLOAT CPDF_VariableText::GetWordWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord,\r
-        FX_FLOAT fCharSpace, FX_INT32 nHorzScale,\r
-        FX_FLOAT fFontSize, FX_FLOAT fWordTail, FX_INT32 nWordStyle)\r
-{\r
-    return (GetCharWidth(nFontIndex, Word, SubWord, nWordStyle) * fFontSize * PVT_FONTSCALE + fCharSpace) * nHorzScale * PVT_PERCENT + fWordTail;\r
-}\r
-FX_FLOAT CPDF_VariableText::GetWordWidth(const CPVT_WordInfo & WordInfo)\r
-{\r
-    return GetWordWidth(GetWordFontIndex(WordInfo), WordInfo.Word, GetSubWord(), GetCharSpace(WordInfo), GetHorzScale(WordInfo),\r
-                        GetWordFontSize(WordInfo), WordInfo.fWordTail,\r
-                        WordInfo.pWordProps ? WordInfo.pWordProps->nWordStyle : 0);\r
-}\r
-FX_FLOAT CPDF_VariableText::GetLineAscent(const CPVT_SectionInfo & SecInfo)\r
-{\r
-    return m_bRichText && SecInfo.pWordProps ? GetFontAscent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :\r
-           GetFontAscent(GetDefaultFontIndex(), GetFontSize());\r
-}\r
-FX_FLOAT CPDF_VariableText::GetLineDescent(const CPVT_SectionInfo & SecInfo)\r
-{\r
-    return m_bRichText && SecInfo.pWordProps ? GetFontDescent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :\r
-           GetFontDescent(GetDefaultFontIndex(), GetFontSize());\r
-}\r
-FX_FLOAT CPDF_VariableText::GetFontAscent(FX_INT32 nFontIndex, FX_FLOAT fFontSize)\r
-{\r
-    return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * PVT_FONTSCALE;\r
-}\r
-FX_FLOAT CPDF_VariableText::GetFontDescent(FX_INT32 nFontIndex, FX_FLOAT fFontSize)\r
-{\r
-    return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * PVT_FONTSCALE;\r
-}\r
-FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)\r
-{\r
-    return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize);\r
-}\r
-FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)\r
-{\r
-    return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize);\r
-}\r
-FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)\r
-{\r
-    return GetFontAscent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));\r
-}\r
-FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)\r
-{\r
-    return GetFontDescent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));\r
-}\r
-FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo & SecInfo)\r
-{\r
-    return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineLeading : m_fLineLeading;\r
-}\r
-FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo & SecInfo)\r
-{\r
-    return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineIndent : 0.0f;\r
-}\r
-FX_INT32 CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo)\r
-{\r
-    return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->nAlignment : this->m_nAlignment;\r
-}\r
-FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo & WordInfo)\r
-{\r
-    return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->fCharSpace : m_fCharSpace;\r
-}\r
-FX_INT32 CPDF_VariableText::GetHorzScale(const CPVT_WordInfo & WordInfo)\r
-{\r
-    return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nHorzScale : m_nHorzScale;\r
-}\r
-void CPDF_VariableText::ClearSectionRightWords(const CPVT_WordPlace & place)\r
-{\r
-    CPVT_WordPlace wordplace = AjustLineHeader(place, TRUE);\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        for (FX_INT32 w = pSection->m_WordArray.GetSize() - 1; w > wordplace.nWordIndex; w--) {\r
-            delete pSection->m_WordArray.GetAt(w);\r
-            pSection->m_WordArray.RemoveAt(w);\r
-        }\r
-    }\r
-}\r
-CPVT_WordPlace CPDF_VariableText::AjustLineHeader(const CPVT_WordPlace & place, FX_BOOL bPrevOrNext) const\r
-{\r
-    if (place.nWordIndex < 0 && place.nLineIndex > 0) {\r
-        if (bPrevOrNext) {\r
-            return GetPrevWordPlace(place);\r
-        } else {\r
-            return GetNextWordPlace(place);\r
-        }\r
-    }\r
-    return place;\r
-}\r
-FX_BOOL CPDF_VariableText::ClearEmptySection(const CPVT_WordPlace & place)\r
-{\r
-    if (place.nSecIndex == 0 && m_SectionArray.GetSize() == 1) {\r
-        return FALSE;\r
-    }\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        if (pSection->m_WordArray.GetSize() == 0) {\r
-            delete pSection;\r
-            m_SectionArray.RemoveAt(place.nSecIndex);\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-void CPDF_VariableText::ClearEmptySections(const CPVT_WordRange & PlaceRange)\r
-{\r
-    CPVT_WordPlace wordplace;\r
-    for (FX_INT32 s = PlaceRange.EndPos.nSecIndex; s > PlaceRange.BeginPos.nSecIndex; s--) {\r
-        wordplace.nSecIndex = s;\r
-        ClearEmptySection(wordplace);\r
-    }\r
-}\r
-void CPDF_VariableText::LinkLatterSection(const CPVT_WordPlace & place)\r
-{\r
-    CPVT_WordPlace oldplace = AjustLineHeader(place, TRUE);\r
-    if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {\r
-        if (CSection * pSection = m_SectionArray.GetAt(oldplace.nSecIndex)) {\r
-            for (FX_INT32 w = 0, sz = pNextSection->m_WordArray.GetSize(); w < sz; w++) {\r
-                if (CPVT_WordInfo * pWord = pNextSection->m_WordArray.GetAt(w)) {\r
-                    oldplace.nWordIndex ++;\r
-                    pSection->AddWord(oldplace, *pWord);\r
-                }\r
-            }\r
-        }\r
-        delete pNextSection;\r
-        m_SectionArray.RemoveAt(place.nSecIndex + 1);\r
-    }\r
-}\r
-void CPDF_VariableText::ClearWords(const CPVT_WordRange & PlaceRange)\r
-{\r
-    CPVT_WordRange NewRange;\r
-    NewRange.BeginPos = AjustLineHeader(PlaceRange.BeginPos, TRUE);\r
-    NewRange.EndPos = AjustLineHeader(PlaceRange.EndPos, TRUE);\r
-    for (FX_INT32 s = NewRange.EndPos.nSecIndex; s >= NewRange.BeginPos.nSecIndex; s--) {\r
-        if (CSection * pSection = m_SectionArray.GetAt(s)) {\r
-            pSection->ClearWords(NewRange);\r
-        }\r
-    }\r
-}\r
-CPVT_WordPlace CPDF_VariableText::ClearLeftWord(const CPVT_WordPlace & place)\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        CPVT_WordPlace leftplace = this->GetPrevWordPlace(place);\r
-        if (leftplace != place) {\r
-            if (leftplace.nSecIndex != place.nSecIndex) {\r
-                if (pSection->m_WordArray.GetSize() == 0) {\r
-                    this->ClearEmptySection(place);\r
-                } else {\r
-                    this->LinkLatterSection(leftplace);\r
-                }\r
-            } else {\r
-                pSection->ClearWord(place);\r
-            }\r
-        }\r
-        return leftplace;\r
-    }\r
-    return place;\r
-}\r
-CPVT_WordPlace CPDF_VariableText::ClearRightWord(const CPVT_WordPlace & place)\r
-{\r
-    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {\r
-        CPVT_WordPlace rightplace = AjustLineHeader(this->GetNextWordPlace(place), FALSE);\r
-        if (rightplace != place) {\r
-            if(rightplace.nSecIndex != place.nSecIndex) {\r
-                LinkLatterSection(place);\r
-            } else {\r
-                pSection->ClearWord(rightplace);\r
-            }\r
-        }\r
-    }\r
-    return place;\r
-}\r
-void CPDF_VariableText::RearrangeAll()\r
-{\r
-    Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));\r
-}\r
-void CPDF_VariableText::RearrangePart(const CPVT_WordRange & PlaceRange)\r
-{\r
-    Rearrange(PlaceRange);\r
-}\r
-CPVT_FloatRect CPDF_VariableText::Rearrange(const CPVT_WordRange & PlaceRange)\r
-{\r
-    CPVT_FloatRect rcRet;\r
-    if (IsValid()) {\r
-        if (m_bAutoFontSize) {\r
-            SetFontSize(GetAutoFontSize());\r
-            rcRet = RearrangeSections(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));\r
-        } else {\r
-            rcRet = RearrangeSections(PlaceRange);\r
-        }\r
-    }\r
-    SetContentRect(rcRet);\r
-    return rcRet;\r
-}\r
-FX_FLOAT CPDF_VariableText::GetAutoFontSize()\r
-{\r
-    FX_INT32 nTotal = sizeof(gFontSizeSteps) / sizeof(FX_BYTE);\r
-    if (IsMultiLine()) {\r
-        nTotal /= 4;\r
-    }\r
-    if (nTotal <= 0) {\r
-        return 0;\r
-    }\r
-    if (GetPlateWidth() <= 0) {\r
-        return 0;\r
-    }\r
-    FX_INT32 nLeft = 0;\r
-    FX_INT32 nRight = nTotal - 1;\r
-    FX_INT32 nMid = nTotal / 2;\r
-    while (nLeft <= nRight) {\r
-        if (IsBigger(gFontSizeSteps[nMid])) {\r
-            nRight = nMid - 1;\r
-            nMid = (nLeft + nRight) / 2;\r
-            continue;\r
-        } else {\r
-            nLeft = nMid + 1;\r
-            nMid = (nLeft + nRight) / 2;\r
-            continue;\r
-        }\r
-    }\r
-    return (FX_FLOAT)gFontSizeSteps[nMid];\r
-}\r
-FX_BOOL        CPDF_VariableText::IsBigger(FX_FLOAT fFontSize)\r
-{\r
-    FX_BOOL bBigger =  FALSE;\r
-    CPVT_Size szTotal;\r
-    for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {\r
-        if (CSection * pSection = m_SectionArray.GetAt(s)) {\r
-            CPVT_Size size = pSection->GetSectionSize(fFontSize);\r
-            szTotal.x = FPDF_MAX(size.x, szTotal.x);\r
-            szTotal.y += size.y;\r
-            if (IsFloatBigger(szTotal.x, GetPlateWidth())\r
-                    || IsFloatBigger(szTotal.y, GetPlateHeight())\r
-               ) {\r
-                bBigger = TRUE;\r
-                break;\r
-            }\r
-        }\r
-    }\r
-    return bBigger;\r
-}\r
-CPVT_FloatRect CPDF_VariableText::RearrangeSections(const CPVT_WordRange & PlaceRange)\r
-{\r
-    CPVT_WordPlace place;\r
-    FX_FLOAT fPosY = 0;\r
-    FX_FLOAT fOldHeight;\r
-    FX_INT32 nSSecIndex = PlaceRange.BeginPos.nSecIndex;\r
-    FX_INT32 nESecIndex = PlaceRange.EndPos.nSecIndex;\r
-    CPVT_FloatRect rcRet;\r
-    for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {\r
-        place.nSecIndex = s;\r
-        if (CSection * pSection = m_SectionArray.GetAt(s)) {\r
-            pSection->SecPlace = place;\r
-            CPVT_FloatRect rcSec = pSection->m_SecInfo.rcSection;\r
-            if (s >= nSSecIndex) {\r
-                if (s <= nESecIndex) {\r
-                    rcSec = pSection->Rearrange();\r
-                    rcSec.top += fPosY;\r
-                    rcSec.bottom += fPosY;\r
-                } else {\r
-                    fOldHeight = pSection->m_SecInfo.rcSection.bottom - pSection->m_SecInfo.rcSection.top;\r
-                    rcSec.top = fPosY;\r
-                    rcSec.bottom = fPosY + fOldHeight;\r
-                }\r
-                pSection->m_SecInfo.rcSection = rcSec;\r
-                pSection->ResetLinePlace();\r
-            }\r
-            if (s == 0) {\r
-                rcRet = rcSec;\r
-            } else {\r
-                rcRet.left = FPDF_MIN(rcSec.left, rcRet.left);\r
-                rcRet.top = FPDF_MIN(rcSec.top, rcRet.top);\r
-                rcRet.right = FPDF_MAX(rcSec.right, rcRet.right);\r
-                rcRet.bottom = FPDF_MAX(rcSec.bottom, rcRet.bottom);\r
-            }\r
-            fPosY += rcSec.Height();\r
-        }\r
-    }\r
-    return rcRet;\r
-}\r
-FX_INT32 CPDF_VariableText::GetCharWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord, FX_INT32 nWordStyle)\r
-{\r
-    if (m_pVTProvider) {\r
-        if (SubWord > 0) {\r
-            return m_pVTProvider->GetCharWidth(nFontIndex, SubWord, nWordStyle);\r
-        } else {\r
-            return m_pVTProvider->GetCharWidth(nFontIndex, Word, nWordStyle);\r
-        }\r
-    }\r
-    return 0;\r
-}\r
-FX_INT32 CPDF_VariableText::GetTypeAscent(FX_INT32 nFontIndex)\r
-{\r
-    return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;\r
-}\r
-FX_INT32 CPDF_VariableText::GetTypeDescent(FX_INT32 nFontIndex)\r
-{\r
-    return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;\r
-}\r
-FX_INT32 CPDF_VariableText::GetWordFontIndex(FX_WORD word, FX_INT32 charset, FX_INT32 nFontIndex)\r
-{\r
-    return m_pVTProvider ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex) : -1;\r
-}\r
-FX_INT32 CPDF_VariableText::GetDefaultFontIndex()\r
-{\r
-    return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;\r
-}\r
-FX_BOOL        CPDF_VariableText::IsLatinWord(FX_WORD word)\r
-{\r
-    return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : FALSE;\r
-}\r
-IPDF_VariableText_Iterator * CPDF_VariableText::GetIterator()\r
-{\r
-    if (!m_pVTIterator) {\r
-        return m_pVTIterator = FX_NEW CPDF_VariableText_Iterator(this);\r
-    }\r
-    return m_pVTIterator;\r
-}\r
-IPDF_VariableText_Provider*    CPDF_VariableText::SetProvider(IPDF_VariableText_Provider * pProvider)\r
-{\r
-    IPDF_VariableText_Provider* pOld = m_pVTProvider;\r
-    m_pVTProvider = pProvider;\r
-    return pOld;\r
-}\r
-CPDF_VariableText_Iterator::CPDF_VariableText_Iterator(CPDF_VariableText * pVT):\r
-    m_pVT(pVT),\r
-    m_CurPos(-1, -1, -1)\r
-{\r
-}\r
-CPDF_VariableText_Iterator::~CPDF_VariableText_Iterator()\r
-{\r
-}\r
-void CPDF_VariableText_Iterator::SetAt(FX_INT32 nWordIndex)\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);\r
-}\r
-void CPDF_VariableText_Iterator::SetAt(const CPVT_WordPlace & place)\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    m_CurPos = place;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::NextWord()\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    if (m_CurPos == m_pVT->GetEndWordPlace()) {\r
-        return FALSE;\r
-    }\r
-    m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);\r
-    return TRUE;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::PrevWord()\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    if (m_CurPos == m_pVT->GetBeginWordPlace()) {\r
-        return FALSE;\r
-    }\r
-    m_CurPos = m_pVT->GetPrevWordPlace(m_CurPos);\r
-    return TRUE;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::NextLine()\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {\r
-        if (m_CurPos.nLineIndex < pSection->m_LineArray.GetSize() - 1) {\r
-            m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1);\r
-            return TRUE;\r
-        } else {\r
-            if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {\r
-                m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);\r
-                return TRUE;\r
-            }\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::PrevLine()\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {\r
-        if (m_CurPos.nLineIndex > 0) {\r
-            m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex - 1, -1);\r
-            return TRUE;\r
-        } else {\r
-            if (m_CurPos.nSecIndex > 0) {\r
-                if (CSection * pLastSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex - 1)) {\r
-                    m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, pLastSection->m_LineArray.GetSize() - 1, -1);\r
-                    return TRUE;\r
-                }\r
-            }\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::NextSection()\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {\r
-        m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::PrevSection()\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    if (m_CurPos.nSecIndex > 0) {\r
-        m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, 0, -1);\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::GetWord(CPVT_Word & word) const\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    word.WordPlace = m_CurPos;\r
-    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {\r
-        if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {\r
-            if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {\r
-                word.Word = pWord->Word;\r
-                word.nCharset = pWord->nCharset;\r
-                word.fWidth = m_pVT->GetWordWidth(*pWord);\r
-                word.ptWord = m_pVT->InToOut(\r
-                                  CPDF_Point(pWord->fWordX + pSection->m_SecInfo.rcSection.left,\r
-                                             pWord->fWordY + pSection->m_SecInfo.rcSection.top) );\r
-                word.fAscent = m_pVT->GetWordAscent(*pWord);\r
-                word.fDescent = m_pVT->GetWordDescent(*pWord);\r
-                if (pWord->pWordProps) {\r
-                    word.WordProps = *pWord->pWordProps;\r
-                }\r
-                word.nFontIndex = m_pVT->GetWordFontIndex(*pWord);\r
-                word.fFontSize = m_pVT->GetWordFontSize(*pWord);\r
-                return TRUE;\r
-            }\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::SetWord(const CPVT_Word & word)\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {\r
-        if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {\r
-            if (pWord->pWordProps) {\r
-                *pWord->pWordProps = word.WordProps;\r
-            }\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::GetLine(CPVT_Line & line) const\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);\r
-    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {\r
-        if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {\r
-            line.ptLine = m_pVT->InToOut(\r
-                              CPDF_Point(pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left,\r
-                                         pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top) );\r
-            line.fLineWidth = pLine->m_LineInfo.fLineWidth;\r
-            line.fLineAscent = pLine->m_LineInfo.fLineAscent;\r
-            line.fLineDescent = pLine->m_LineInfo.fLineDescent;\r
-            line.lineEnd = pLine->GetEndWordPlace();\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::GetSection(CPVT_Section & section) const\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1);\r
-    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {\r
-        section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection);\r
-        if (pSection->m_SecInfo.pSecProps) {\r
-            section.SecProps = *pSection->m_SecInfo.pSecProps;\r
-        }\r
-        if (pSection->m_SecInfo.pWordProps) {\r
-            section.WordProps = *pSection->m_SecInfo.pWordProps;\r
-        }\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-FX_BOOL        CPDF_VariableText_Iterator::SetSection(const CPVT_Section & section)\r
-{\r
-    ASSERT(m_pVT != NULL);\r
-    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {\r
-        if (pSection->m_SecInfo.pSecProps) {\r
-            *pSection->m_SecInfo.pSecProps = section.SecProps;\r
-        }\r
-        if (pSection->m_SecInfo.pWordProps) {\r
-            *pSection->m_SecInfo.pWordProps = section.WordProps;\r
-        }\r
-        return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
+// 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/fpdfdoc/fpdf_doc.h"
+#include "../../include/fpdfdoc/fpdf_vt.h"
+#include "pdf_vt.h"
+const uint8_t gFontSizeSteps[] = {     4, 6, 8, 9, 10, 12, 14, 18, 20, 25,     30, 35, 40, 45, 50,     55, 60, 70, 80, 90,     100, 110, 120, 130, 144};
+#define PVT_RETURN_LENGTH                                      1
+#define PVT_DEFAULT_FONTSIZE                           18.0f
+#define PVTWORD_SCRIPT_NORMAL                          0
+#define PVTWORD_SCRIPT_SUPER                           1
+#define PVTWORD_SCRIPT_SUB                                     2
+#define        PVT_FONTSCALE                                           0.001f
+#define PVT_PERCENT                                                    0.01f
+#define PVT_HALF                                                       0.5f
+CLine::CLine()
+{
+}
+CLine::~CLine()
+{
+}
+CPVT_WordPlace CLine::GetBeginWordPlace() const
+{
+    return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, -1);
+}
+CPVT_WordPlace CLine::GetEndWordPlace() const
+{
+    return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, m_LineInfo.nEndWordIndex);
+}
+CPVT_WordPlace CLine::GetPrevWordPlace(const CPVT_WordPlace & place) const
+{
+    if (place.nWordIndex > m_LineInfo.nEndWordIndex) {
+        return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, m_LineInfo.nEndWordIndex);
+    }
+    return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, place.nWordIndex - 1);
+}
+CPVT_WordPlace CLine::GetNextWordPlace(const CPVT_WordPlace & place) const
+{
+    if (place.nWordIndex < m_LineInfo.nBeginWordIndex) {
+        return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, m_LineInfo.nBeginWordIndex);
+    }
+    return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, place.nWordIndex + 1);
+}
+CSection::CSection(CPDF_VariableText * pVT) : m_pVT(pVT)
+{
+}
+CSection::~CSection()
+{
+    ResetAll();
+}
+void CSection::ResetAll()
+{
+    ResetWordArray();
+    ResetLineArray();
+}
+void CSection::ResetLineArray()
+{
+    m_LineArray.RemoveAll();
+}
+void CSection::ResetWordArray()
+{
+    for (int32_t i = 0, sz = m_WordArray.GetSize(); i < sz; i++) {
+        delete m_WordArray.GetAt(i);
+    }
+    m_WordArray.RemoveAll();
+}
+void CSection::ResetLinePlace()
+{
+    for (int32_t i = 0, sz = m_LineArray.GetSize(); i < sz; i++) {
+        if (CLine * pLine = m_LineArray.GetAt(i)) {
+            pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1);
+        }
+    }
+}
+CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
+{
+    if (CPVT_WordInfo * pWord = FX_NEW CPVT_WordInfo(wordinfo)) {
+        int32_t nWordIndex = FPDF_MAX(FPDF_MIN(place.nWordIndex, this->m_WordArray.GetSize()), 0);
+        if (nWordIndex == m_WordArray.GetSize()) {
+            m_WordArray.Add(pWord);
+        } else {
+            m_WordArray.InsertAt(nWordIndex, pWord);
+        }
+    }
+    return place;
+}
+CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo & lineinfo)
+{
+    return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.Add(lineinfo), -1);
+}
+CPVT_FloatRect CSection::Rearrange()
+{
+    ASSERT(m_pVT != NULL);
+    if (m_pVT->m_nCharArray > 0) {
+        return CTypeset(this).CharArray();
+    } else {
+        return CTypeset(this).Typeset();
+    }
+}
+CPVT_Size CSection::GetSectionSize(FX_FLOAT fFontSize)
+{
+    return CTypeset(this).GetEditSize(fFontSize);
+}
+CPVT_WordPlace CSection::GetBeginWordPlace() const
+{
+    if (CLine * pLine = m_LineArray.GetAt(0)) {
+        return pLine->GetBeginWordPlace();
+    } else {
+        return SecPlace;
+    }
+}
+CPVT_WordPlace CSection::GetEndWordPlace() const
+{
+    if (CLine * pLine = m_LineArray.GetAt(m_LineArray.GetSize() - 1)) {
+        return pLine->GetEndWordPlace();
+    } else {
+        return this->SecPlace;
+    }
+}
+CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace & place) const
+{
+    if (place.nLineIndex < 0) {
+        return GetBeginWordPlace();
+    }
+    if (place.nLineIndex >= m_LineArray.GetSize()) {
+        return GetEndWordPlace();
+    }
+    if (CLine * pLine = m_LineArray.GetAt(place.nLineIndex)) {
+        if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) {
+            return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
+        } else if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
+            if (CLine * pPrevLine = m_LineArray.GetAt(place.nLineIndex - 1)) {
+                return pPrevLine->GetEndWordPlace();
+            }
+        } else {
+            return pLine->GetPrevWordPlace(place);
+        }
+    }
+    return place;
+}
+CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace & place) const
+{
+    if (place.nLineIndex < 0) {
+        return GetBeginWordPlace();
+    }
+    if (place.nLineIndex >= m_LineArray.GetSize()) {
+        return GetEndWordPlace();
+    }
+    if (CLine * pLine = m_LineArray.GetAt(place.nLineIndex)) {
+        if (place.nWordIndex >= pLine->m_LineInfo.nEndWordIndex) {
+            if (CLine * pNextLine = m_LineArray.GetAt(place.nLineIndex + 1)) {
+                return pNextLine->GetBeginWordPlace();
+            }
+        } else {
+            return pLine->GetNextWordPlace(place);
+        }
+    }
+    return place;
+}
+void CSection::UpdateWordPlace(CPVT_WordPlace & place) const
+{
+    int32_t nLeft = 0;
+    int32_t nRight = m_LineArray.GetSize() - 1;
+    int32_t nMid = (nLeft + nRight) / 2;
+    while (nLeft <= nRight) {
+        if (CLine * pLine = m_LineArray.GetAt(nMid)) {
+            if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
+                nRight = nMid - 1;
+                nMid = (nLeft + nRight) / 2;
+            } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) {
+                nLeft = nMid + 1;
+                nMid = (nLeft + nRight) / 2;
+            } else {
+                place.nLineIndex = nMid;
+                return;
+            }
+        } else {
+            break;
+        }
+    }
+}
+CPVT_WordPlace CSection::SearchWordPlace(const CPDF_Point & point) const
+{
+    ASSERT(m_pVT != NULL);
+    CPVT_WordPlace place = GetBeginWordPlace();
+    FX_BOOL bUp = TRUE;
+    FX_BOOL bDown = TRUE;
+    int32_t nLeft = 0;
+    int32_t nRight = m_LineArray.GetSize() - 1;
+    int32_t nMid = m_LineArray.GetSize() / 2;
+    FX_FLOAT fTop = 0;
+    FX_FLOAT fBottom = 0;
+    while (nLeft <= nRight) {
+        if (CLine * pLine = m_LineArray.GetAt(nMid)) {
+            fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent - m_pVT->GetLineLeading(m_SecInfo);
+            fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent;
+            if (IsFloatBigger(point.y, fTop)) {
+                bUp = FALSE;
+            }
+            if (IsFloatSmaller(point.y, fBottom)) {
+                bDown = FALSE;
+            }
+            if (IsFloatSmaller(point.y, fTop)) {
+                nRight = nMid - 1;
+                nMid = (nLeft + nRight) / 2;
+                continue;
+            } else if (IsFloatBigger(point.y, fBottom)) {
+                nLeft = nMid + 1;
+                nMid = (nLeft + nRight) / 2;
+                continue;
+            } else {
+                place = SearchWordPlace(point.x,
+                                        CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), pLine->GetEndWordPlace())
+                                       );
+                place.nLineIndex = nMid;
+                return place;
+            }
+        }
+    }
+    if (bUp) {
+        place = GetBeginWordPlace();
+    }
+    if (bDown) {
+        place = GetEndWordPlace();
+    }
+    return place;
+}
+CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, const CPVT_WordPlace & lineplace) const
+{
+    if (CLine * pLine = m_LineArray.GetAt(lineplace.nLineIndex)) {
+        return SearchWordPlace(fx - m_SecInfo.rcSection.left,
+                               CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), pLine->GetEndWordPlace()));
+    }
+    return GetBeginWordPlace();
+}
+CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, const CPVT_WordRange & range) const
+{
+    CPVT_WordPlace wordplace = range.BeginPos;
+    wordplace.nWordIndex = -1;
+    if (!m_pVT)        {
+        return wordplace;
+    }
+    int32_t nLeft = range.BeginPos.nWordIndex;
+    int32_t nRight = range.EndPos.nWordIndex + 1;
+    int32_t nMid = (nLeft + nRight) / 2;
+    while (nLeft < nRight) {
+        if (nMid == nLeft) {
+            break;
+        }
+        if (nMid == nRight) {
+            nMid--;
+            break;
+        }
+        if (CPVT_WordInfo * pWord = m_WordArray.GetAt(nMid)) {
+            if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {
+                nLeft = nMid;
+                nMid = (nLeft + nRight) / 2;
+                continue;
+            } else {
+                nRight = nMid;
+                nMid = (nLeft + nRight) / 2;
+                continue;
+            }
+        } else {
+            break;
+        }
+    }
+    if (CPVT_WordInfo * pWord = m_WordArray.GetAt(nMid)) {
+        if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {
+            wordplace.nWordIndex = nMid;
+        }
+    }
+    return wordplace;
+}
+void CSection::ClearLeftWords(int32_t nWordIndex)
+{
+    for (int32_t i = nWordIndex; i >= 0; i--) {
+        delete m_WordArray.GetAt(i);
+        m_WordArray.RemoveAt(i);
+    }
+}
+void CSection::ClearRightWords(int32_t nWordIndex)
+{
+    for (int32_t i = m_WordArray.GetSize() - 1; i > nWordIndex; i--) {
+        delete m_WordArray.GetAt(i);
+        m_WordArray.RemoveAt(i);
+    }
+}
+void CSection::ClearMidWords(int32_t nBeginIndex, int32_t nEndIndex)
+{
+    for (int32_t i = nEndIndex; i > nBeginIndex; i--) {
+        delete m_WordArray.GetAt(i);
+        m_WordArray.RemoveAt(i);
+    }
+}
+void CSection::ClearWords(const CPVT_WordRange & PlaceRange)
+{
+    CPVT_WordPlace SecBeginPos = GetBeginWordPlace();
+    CPVT_WordPlace SecEndPos = GetEndWordPlace();
+    if (PlaceRange.BeginPos.WordCmp(SecBeginPos) >= 0) {
+        if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
+            ClearMidWords(PlaceRange.BeginPos.nWordIndex, PlaceRange.EndPos.nWordIndex);
+        } else {
+            ClearRightWords(PlaceRange.BeginPos.nWordIndex);
+        }
+    } else if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
+        ClearLeftWords(PlaceRange.EndPos.nWordIndex);
+    } else {
+        ResetWordArray();
+    }
+}
+void CSection::ClearWord(const CPVT_WordPlace & place)
+{
+    delete m_WordArray.GetAt(place.nWordIndex);
+    m_WordArray.RemoveAt(place.nWordIndex);
+}
+CTypeset::CTypeset(CSection * pSection) : m_rcRet(0.0f, 0.0f, 0.0f, 0.0f), m_pVT(pSection->m_pVT), m_pSection(pSection)
+{
+}
+CTypeset::~CTypeset()
+{
+}
+CPVT_FloatRect CTypeset::CharArray()
+{
+    ASSERT(m_pSection != NULL);
+    ASSERT(m_pVT != NULL);
+    FX_FLOAT fLineAscent = m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());
+    FX_FLOAT fLineDescent = m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());
+    m_rcRet.Default();
+    FX_FLOAT x = 0.0f, y = 0.0f;
+    FX_FLOAT fNextWidth;
+    int32_t nStart = 0;
+    FX_FLOAT fNodeWidth = m_pVT->GetPlateWidth() / (m_pVT->m_nCharArray <= 0 ? 1 : m_pVT->m_nCharArray);
+    if (CLine * pLine = m_pSection->m_LineArray.GetAt(0)) {
+        x = 0.0f;
+        y +=  m_pVT->GetLineLeading(m_pSection->m_SecInfo);
+        y += fLineAscent;
+        nStart = 0;
+        switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
+            case 0:
+                pLine->m_LineInfo.fLineX = fNodeWidth * PVT_HALF;
+                break;
+            case 1:
+                nStart = (m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize()) / 2;
+                pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;
+                break;
+            case 2:
+                nStart = m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize();
+                pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;
+                break;
+        }
+        for (int32_t w = 0, sz = m_pSection->m_WordArray.GetSize(); w < sz; w++) {
+            if (w >= m_pVT->m_nCharArray) {
+                break;
+            }
+            fNextWidth = 0;
+            if (CPVT_WordInfo * pNextWord = (CPVT_WordInfo *)m_pSection->m_WordArray.GetAt(w + 1)) {
+                pNextWord->fWordTail = 0;
+                fNextWidth = m_pVT->GetWordWidth(*pNextWord);
+            }
+            if (CPVT_WordInfo * pWord = (CPVT_WordInfo *)m_pSection->m_WordArray.GetAt(w)) {
+                pWord->fWordTail = 0;
+                FX_FLOAT fWordWidth = m_pVT->GetWordWidth(*pWord);
+                FX_FLOAT fWordAscent = m_pVT->GetWordAscent(*pWord);
+                FX_FLOAT fWordDescent = m_pVT->GetWordDescent(*pWord);
+                x = (FX_FLOAT)(fNodeWidth * (w + nStart + 0.5) - fWordWidth * PVT_HALF);
+                pWord->fWordX = x;
+                pWord->fWordY = y;
+                if (w == 0) {
+                    pLine->m_LineInfo.fLineX = x;
+                }
+                if (w != m_pSection->m_WordArray.GetSize() - 1)
+                    pWord->fWordTail = (fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF > 0 ?
+                                        fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF : 0);
+                else {
+                    pWord->fWordTail = 0;
+                }
+                x += fWordWidth;
+                fLineAscent = FPDF_MAX(fLineAscent, fWordAscent);
+                fLineDescent = FPDF_MIN(fLineDescent, fWordDescent);
+            }
+        }
+        pLine->m_LineInfo.nBeginWordIndex = 0;
+        pLine->m_LineInfo.nEndWordIndex = m_pSection->m_WordArray.GetSize() - 1;
+        pLine->m_LineInfo.fLineY = y;
+        pLine->m_LineInfo.fLineWidth =         x - pLine->m_LineInfo.fLineX;
+        pLine->m_LineInfo.fLineAscent = fLineAscent;
+        pLine->m_LineInfo.fLineDescent = fLineDescent;
+        y += (-fLineDescent);
+    }
+    return m_rcRet = CPVT_FloatRect(0, 0, x, y);
+}
+CPVT_Size CTypeset::GetEditSize(FX_FLOAT fFontSize)
+{
+    ASSERT(m_pSection != NULL);
+    ASSERT(m_pVT != NULL);
+    SplitLines(FALSE, fFontSize);
+    return CPVT_Size(m_rcRet.Width(), m_rcRet.Height());
+}
+CPVT_FloatRect CTypeset::Typeset()
+{
+    ASSERT(m_pSection != NULL);
+    ASSERT(m_pVT != NULL);
+    m_pSection->m_LineArray.Empty();
+    SplitLines(TRUE, 0.0f);
+    m_pSection->m_LineArray.Clear();
+    OutputLines();
+    return m_rcRet;
+}
+static int special_chars[128] = {
+    0x0000, 0x000C, 0x0008, 0x000C, 0x0008, 0x0000, 0x0020, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0008, 0x0008, 0x0000, 0x0010, 0x0000, 0x0000, 0x0028,
+    0x000C, 0x0008, 0x0000, 0x0000, 0x0028, 0x0028, 0x0028, 0x0028,
+    0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+    0x0002, 0x0002, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0008,
+    0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+    0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+    0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+    0x0001, 0x0001, 0x0001, 0x000C, 0x0000, 0x0008, 0x0000, 0x0000,
+    0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+    0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+    0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+    0x0001, 0x0001, 0x0001, 0x000C, 0x0000, 0x0008, 0x0000, 0x0000,
+};
+static FX_BOOL IsLatin(FX_WORD word)
+{
+    if (word <= 0x007F) {
+        if (special_chars[word] & 0x0001) {
+            return TRUE;
+        }
+    }
+    if ((word >= 0x00C0 && word <= 0x00FF) ||
+            (word >= 0x0100 && word <= 0x024F) ||
+            (word >= 0x1E00 && word <= 0x1EFF) ||
+            (word >= 0x2C60 && word <= 0x2C7F) ||
+            (word >= 0xA720 && word <= 0xA7FF) ||
+            (word >= 0xFF21 && word <= 0xFF3A) ||
+            (word >= 0xFF41 && word <= 0xFF5A)) {
+        return TRUE;
+    }
+    return FALSE;
+}
+static FX_BOOL IsDigit(FX_DWORD word)
+{
+    return (word >= 0x0030 && word <= 0x0039) ? TRUE : FALSE;
+}
+static FX_BOOL IsCJK(FX_DWORD word)
+{
+    if ((word >= 0x1100 && word <= 0x11FF) ||
+            (word >= 0x2E80 && word <= 0x2FFF) ||
+            (word >= 0x3040 && word <= 0x9FBF) ||
+            (word >= 0xAC00 && word <= 0xD7AF) ||
+            (word >= 0xF900 && word <= 0xFAFF) ||
+            (word >= 0xFE30 && word <= 0xFE4F) ||
+            (word >= 0x20000 && word <= 0x2A6DF) ||
+            (word >= 0x2F800 && word <= 0x2FA1F)) {
+        return TRUE;
+    }
+    if (word >= 0x3000 && word <= 0x303F) {
+        if (word == 0x3005 || word == 0x3006 || word == 0x3021 || word == 0x3022 ||
+                word == 0x3023 || word == 0x3024 || word == 0x3025 || word == 0x3026 ||
+                word == 0x3027 || word == 0x3028 || word == 0x3029 || word == 0x3031 ||
+                word == 0x3032 || word == 0x3033 || word == 0x3034 || word == 0x3035) {
+            return TRUE;
+        }
+        return FALSE;
+    }
+    if (word >= 0xFF66 && word <= 0xFF9D) {
+        return TRUE;
+    }
+    return FALSE;
+}
+static FX_BOOL IsPunctuation(FX_DWORD word)
+{
+    if (word <= 0x007F) {
+        if ((special_chars[word] >> 3) & 1) {
+            return TRUE;
+        }
+    } else if (word >= 0x0080 && word <= 0x00FF) {
+        if (word == 0x0082 || word == 0x0084 || word == 0x0085 || word == 0x0091 ||
+                word == 0x0092 || word == 0x0093 || word <= 0x0094 || word == 0x0096 ||
+                word == 0x00B4 || word == 0x00B8) {
+            return TRUE;
+        }
+    } else if (word >= 0x2000 && word <= 0x206F) {
+        if (word == 0x2010 || word == 0x2011 || word == 0x2012 || word == 0x2013 ||
+                word == 0x2018 || word == 0x2019 || word == 0x201A || word == 0x201B ||
+                word == 0x201C || word == 0x201D || word == 0x201E || word == 0x201F ||
+                word == 0x2032 || word == 0x2033 || word == 0x2034 || word == 0x2035 ||
+                word == 0x2036 || word == 0x2037 || word == 0x203C || word == 0x203D ||
+                word == 0x203E || word == 0x2044) {
+            return TRUE;
+        }
+    } else if (word >= 0x3000 && word <= 0x303F) {
+        if (word == 0x3001 || word == 0x3002 || word == 0x3003 || word == 0x3005 ||
+                word == 0x3009 || word == 0x300A || word == 0x300B || word == 0x300C ||
+                word == 0x300D || word == 0x300F || word == 0x300E || word == 0x3010 ||
+                word == 0x3011 || word == 0x3014 || word == 0x3015 || word == 0x3016 ||
+                word == 0x3017 || word == 0x3018 || word == 0x3019 || word == 0x301A ||
+                word == 0x301B || word == 0x301D || word == 0x301E || word == 0x301F) {
+            return TRUE;
+        }
+    } else if (word >= 0xFE50 && word <= 0xFE6F) {
+        if ((word >= 0xFE50 && word <= 0xFE5E) || word == 0xFE63) {
+            return TRUE;
+        }
+    } else if (word >= 0xFF00 && word <= 0xFFEF) {
+        if (word == 0xFF01 || word == 0xFF02 || word == 0xFF07 || word == 0xFF08 ||
+                word == 0xFF09 || word == 0xFF0C || word == 0xFF0E || word == 0xFF0F ||
+                word == 0xFF1A || word == 0xFF1B || word == 0xFF1F || word == 0xFF3B ||
+                word == 0xFF3D || word == 0xFF40 || word == 0xFF5B || word == 0xFF5C ||
+                word == 0xFF5D || word == 0xFF61 || word == 0xFF62 || word == 0xFF63 ||
+                word == 0xFF64 || word == 0xFF65 || word == 0xFF9E || word == 0xFF9F) {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+static FX_BOOL IsConnectiveSymbol(FX_DWORD word)
+{
+    if (word <= 0x007F) {
+        if ((special_chars[word] >> 5) & 1) {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+static FX_BOOL IsOpenStylePunctuation(FX_DWORD word)
+{
+    if (word <= 0x007F) {
+        if ((special_chars[word] >> 2) & 1) {
+            return TRUE;
+        }
+    } else if (word == 0x300A || word == 0x300C || word == 0x300E || word == 0x3010 ||
+               word == 0x3014 || word == 0x3016 || word == 0x3018 || word == 0x301A ||
+               word == 0xFF08 || word == 0xFF3B || word == 0xFF5B || word == 0xFF62) {
+        return TRUE;
+    }
+    return FALSE;
+}
+static FX_BOOL IsCurrencySymbol(FX_WORD word)
+{
+    if (word == 0x0024 || word == 0x0080 || word == 0x00A2 || word == 0x00A3 ||
+            word == 0x00A4 || word == 0x00A5 || (word >= 0x20A0 && word <= 0x20CF) ||
+            word == 0xFE69 || word == 0xFF04 || word == 0xFFE0 || word == 0xFFE1 ||
+            word == 0xFFE5 || word == 0xFFE6) {
+        return TRUE;
+    }
+    return FALSE;
+}
+static FX_BOOL IsPrefixSymbol(FX_WORD word)
+{
+    if (IsCurrencySymbol(word)) {
+        return TRUE;
+    }
+    if (word == 0x2116) {
+        return TRUE;
+    }
+    return FALSE;
+}
+static FX_BOOL IsSpace(FX_WORD word)
+{
+    return (word == 0x0020 || word == 0x3000) ? TRUE : FALSE;
+}
+static FX_BOOL NeedDivision(FX_WORD prevWord, FX_WORD curWord)
+{
+    if ((IsLatin(prevWord) || IsDigit(prevWord)) && (IsLatin(curWord) || IsDigit(curWord))) {
+        return FALSE;
+    } else if (IsSpace(curWord) || IsPunctuation(curWord)) {
+        return FALSE;
+    } else if (IsConnectiveSymbol(prevWord) || IsConnectiveSymbol(curWord)) {
+        return FALSE;
+    } else if (IsSpace(prevWord) || IsPunctuation(prevWord)) {
+        return TRUE;
+    } else if (IsPrefixSymbol(prevWord)) {
+        return FALSE;
+    } else if (IsPrefixSymbol(curWord) || IsCJK(curWord)) {
+        return TRUE;
+    } else if (IsCJK(prevWord)) {
+        return TRUE;
+    }
+    return FALSE;
+}
+void CTypeset::SplitLines(FX_BOOL bTypeset, FX_FLOAT fFontSize)
+{
+    ASSERT(m_pVT != NULL);
+    ASSERT(m_pSection != NULL);
+    int32_t nLineHead = 0;
+    int32_t nLineTail = 0;
+    FX_FLOAT fMaxX = 0.0f, fMaxY = 0.0f;
+    FX_FLOAT fLineWidth = 0.0f, fBackupLineWidth = 0.0f;
+    FX_FLOAT fLineAscent = 0.0f, fBackupLineAscent = 0.0f;
+    FX_FLOAT fLineDescent = 0.0f, fBackupLineDescent = 0.0f;
+    int32_t nWordStartPos = 0;
+    FX_BOOL bFullWord = FALSE;
+    int32_t nLineFullWordIndex = 0;
+    int32_t nCharIndex = 0;
+    CPVT_LineInfo line;
+    FX_FLOAT fWordWidth = 0;
+    FX_FLOAT fTypesetWidth = FPDF_MAX(m_pVT->GetPlateWidth() - m_pVT->GetLineIndent(m_pSection->m_SecInfo), 0.0f);
+    int32_t nTotalWords = m_pSection->m_WordArray.GetSize();
+    FX_BOOL bOpened = FALSE;
+    if (nTotalWords > 0) {
+        int32_t i = 0;
+        while (i < nTotalWords) {
+            CPVT_WordInfo * pWord = m_pSection->m_WordArray.GetAt(i);
+            CPVT_WordInfo* pOldWord = pWord;
+            if (i > 0) {
+                pOldWord = m_pSection->m_WordArray.GetAt(i - 1);
+            }
+            if (pWord) {
+                if (bTypeset) {
+                    fLineAscent = FPDF_MAX(fLineAscent, m_pVT->GetWordAscent(*pWord, TRUE));
+                    fLineDescent = FPDF_MIN(fLineDescent, m_pVT->GetWordDescent(*pWord, TRUE));
+                    fWordWidth = m_pVT->GetWordWidth(*pWord);
+                } else {
+                    fLineAscent = FPDF_MAX(fLineAscent, m_pVT->GetWordAscent(*pWord, fFontSize));
+                    fLineDescent = FPDF_MIN(fLineDescent, m_pVT->GetWordDescent(*pWord, fFontSize));
+                    fWordWidth = m_pVT->GetWordWidth(pWord->nFontIndex,
+                                                     pWord->Word,
+                                                     m_pVT->m_wSubWord,
+                                                     m_pVT->m_fCharSpace,
+                                                     m_pVT->m_nHorzScale,
+                                                     fFontSize,
+                                                     pWord->fWordTail,
+                                                     0);
+                }
+                if (!bOpened) {
+                    if (IsOpenStylePunctuation(pWord->Word)) {
+                        bOpened = TRUE;
+                        bFullWord = TRUE;
+                    } else if (pOldWord != NULL) {
+                        if (NeedDivision(pOldWord->Word, pWord->Word)) {
+                            bFullWord = TRUE;
+                        }
+                    }
+                } else {
+                    if (!IsSpace(pWord->Word) && !IsOpenStylePunctuation(pWord->Word)) {
+                        bOpened = FALSE;
+                    }
+                }
+                if (bFullWord) {
+                    bFullWord = FALSE;
+                    if (nCharIndex > 0) {
+                        nLineFullWordIndex ++;
+                    }
+                    nWordStartPos = i;
+                    fBackupLineWidth = fLineWidth;
+                    fBackupLineAscent = fLineAscent;
+                    fBackupLineDescent = fLineDescent;
+                }
+                nCharIndex++;
+            }
+            if (m_pVT->m_bLimitWidth && fTypesetWidth > 0 &&
+                    fLineWidth + fWordWidth > fTypesetWidth) {
+                if (nLineFullWordIndex > 0) {
+                    i = nWordStartPos;
+                    fLineWidth = fBackupLineWidth;
+                    fLineAscent = fBackupLineAscent;
+                    fLineDescent = fBackupLineDescent;
+                }
+                if (nCharIndex == 1) {
+                    fLineWidth =  fWordWidth;
+                    i++;
+                }
+                nLineTail = i - 1;
+                if (bTypeset) {
+                    line.nBeginWordIndex = nLineHead;
+                    line.nEndWordIndex = nLineTail;
+                    line.nTotalWord = nLineTail - nLineHead + 1;
+                    line.fLineWidth = fLineWidth;
+                    line.fLineAscent = fLineAscent;
+                    line.fLineDescent = fLineDescent;
+                    m_pSection->AddLine(line);
+                }
+                fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo));
+                fMaxY += (-fLineDescent);
+                fMaxX = FPDF_MAX(fLineWidth, fMaxX);
+                nLineHead = i;
+                fLineWidth = 0.0f;
+                fLineAscent = 0.0f;
+                fLineDescent = 0.0f;
+                nCharIndex = 0;
+                nLineFullWordIndex = 0;
+                bFullWord = FALSE;
+            } else {
+                fLineWidth += fWordWidth;
+                i++;
+            }
+        }
+        if (nLineHead <= nTotalWords - 1) {
+            nLineTail = nTotalWords - 1;
+            if (bTypeset) {
+                line.nBeginWordIndex = nLineHead;
+                line.nEndWordIndex = nLineTail;
+                line.nTotalWord = nLineTail - nLineHead + 1;
+                line.fLineWidth = fLineWidth;
+                line.fLineAscent = fLineAscent;
+                line.fLineDescent = fLineDescent;
+                m_pSection->AddLine(line);
+            }
+            fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo));
+            fMaxY += (-fLineDescent);
+            fMaxX = FPDF_MAX(fLineWidth, fMaxX);
+        }
+    } else {
+        if (bTypeset) {
+            fLineAscent = m_pVT->GetLineAscent(m_pSection->m_SecInfo);
+            fLineDescent = m_pVT->GetLineDescent(m_pSection->m_SecInfo);
+        } else {
+            fLineAscent = m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), fFontSize);
+            fLineDescent = m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), fFontSize);
+        }
+        if (bTypeset) {
+            line.nBeginWordIndex = -1;
+            line.nEndWordIndex = -1;
+            line.nTotalWord = 0;
+            line.fLineWidth = 0;
+            line.fLineAscent = fLineAscent;
+            line.fLineDescent = fLineDescent;
+            m_pSection->AddLine(line);
+        }
+        fMaxY += (m_pVT->GetLineLeading(m_pSection->m_SecInfo) + fLineAscent + (-fLineDescent));
+    }
+    m_rcRet = CPVT_FloatRect(0, 0, fMaxX, fMaxY);
+}
+void CTypeset::OutputLines()
+{
+    ASSERT(m_pVT != NULL);
+    ASSERT(m_pSection != NULL);
+    FX_FLOAT fMinX = 0.0f, fMinY = 0.0f, fMaxX = 0.0f, fMaxY = 0.0f;
+    FX_FLOAT fPosX = 0.0f, fPosY = 0.0f;
+    FX_FLOAT fLineIndent = m_pVT->GetLineIndent(m_pSection->m_SecInfo);
+    FX_FLOAT fTypesetWidth = FPDF_MAX(m_pVT->GetPlateWidth() - fLineIndent, 0.0f);
+    switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
+        default:
+        case 0:
+            fMinX = 0.0f;
+            break;
+        case 1:
+            fMinX = (fTypesetWidth - m_rcRet.Width())  * PVT_HALF;
+            break;
+        case 2:
+            fMinX = fTypesetWidth - m_rcRet.Width();
+            break;
+    }
+    fMaxX = fMinX + m_rcRet.Width();
+    fMinY = 0.0f;
+    fMaxY = m_rcRet.Height();
+    int32_t nTotalLines = m_pSection->m_LineArray.GetSize();
+    if (nTotalLines > 0) {
+        m_pSection->m_SecInfo.nTotalLine = nTotalLines;
+        for (int32_t l = 0; l < nTotalLines; l++) {
+            if (CLine * pLine = m_pSection->m_LineArray.GetAt(l)) {
+                switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
+                    default:
+                    case 0:
+                        fPosX = 0;
+                        break;
+                    case 1:
+                        fPosX = (fTypesetWidth - pLine->m_LineInfo.fLineWidth) * PVT_HALF;
+                        break;
+                    case 2:
+                        fPosX = fTypesetWidth - pLine->m_LineInfo.fLineWidth;
+                        break;
+                }
+                fPosX += fLineIndent;
+                fPosY += m_pVT->GetLineLeading(m_pSection->m_SecInfo);
+                fPosY += pLine->m_LineInfo.fLineAscent;
+                pLine->m_LineInfo.fLineX = fPosX - fMinX;
+                pLine->m_LineInfo.fLineY = fPosY - fMinY;
+                for (int32_t w = pLine->m_LineInfo.nBeginWordIndex; w <= pLine->m_LineInfo.nEndWordIndex; w++) {
+                    if (CPVT_WordInfo * pWord = m_pSection->m_WordArray.GetAt(w)) {
+                        pWord->fWordX = fPosX - fMinX;
+                        if (pWord->pWordProps) {
+                            switch (pWord->pWordProps->nScriptType) {
+                                default:
+                                case PVTWORD_SCRIPT_NORMAL:
+                                    pWord->fWordY = fPosY - fMinY;
+                                    break;
+                                case PVTWORD_SCRIPT_SUPER:
+                                    pWord->fWordY = fPosY - m_pVT->GetWordAscent(*pWord) - fMinY;
+                                    break;
+                                case PVTWORD_SCRIPT_SUB:
+                                    pWord->fWordY = fPosY - m_pVT->GetWordDescent(*pWord) - fMinY;
+                                    break;
+                            }
+                        } else {
+                            pWord->fWordY = fPosY - fMinY;
+                        }
+                        fPosX += m_pVT->GetWordWidth(*pWord);
+                    }
+                }
+                fPosY += (-pLine->m_LineInfo.fLineDescent);
+            }
+        }
+    }
+    m_rcRet = CPVT_FloatRect(fMinX, fMinY, fMaxX, fMaxY);
+}
+CPDF_VariableText::CPDF_VariableText() :
+    m_nLimitChar(0),
+    m_nCharArray(0),
+    m_bMultiLine(FALSE),
+    m_bLimitWidth(FALSE),
+    m_bAutoFontSize(FALSE),
+    m_nAlignment(0),
+    m_fLineLeading(0.0f),
+    m_fCharSpace(0.0f),
+    m_nHorzScale(100),
+    m_wSubWord(0),
+    m_fFontSize(0.0f),
+    m_bInitial(FALSE),
+    m_bRichText(FALSE),
+    m_pVTProvider(NULL),
+    m_pVTIterator(NULL)
+{
+}
+CPDF_VariableText::~CPDF_VariableText()
+{
+    if (m_pVTIterator) {
+        delete m_pVTIterator;
+        m_pVTIterator = NULL;
+    }
+    ResetAll();
+}
+void CPDF_VariableText::Initialize()
+{
+    if (!m_bInitial) {
+        CPVT_SectionInfo secinfo;
+        if (m_bRichText) {
+            secinfo.pSecProps = FX_NEW CPVT_SecProps(0.0f, 0.0f, 0);
+            secinfo.pWordProps = FX_NEW CPVT_WordProps(GetDefaultFontIndex(), PVT_DEFAULT_FONTSIZE, 0, 0, 0);
+        }
+        CPVT_WordPlace place;
+        place.nSecIndex = 0;
+        AddSection(place, secinfo);
+        CPVT_LineInfo lineinfo;
+        lineinfo.fLineAscent = GetFontAscent(GetDefaultFontIndex(), GetFontSize());
+        lineinfo.fLineDescent = GetFontDescent(GetDefaultFontIndex(), GetFontSize());
+        AddLine(place, lineinfo);
+        if (CSection * pSection = m_SectionArray.GetAt(0)) {
+            pSection->ResetLinePlace();
+        }
+        m_bInitial = TRUE;
+    }
+}
+void CPDF_VariableText::ResetAll()
+{
+    m_bInitial = FALSE;
+    ResetSectionArray();
+}
+CPVT_WordPlace CPDF_VariableText::InsertWord(const CPVT_WordPlace & place, FX_WORD word, int32_t charset,
+        const CPVT_WordProps * pWordProps)
+{
+    int32_t nTotlaWords = this->GetTotalWords();
+    if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {
+        return place;
+    }
+    if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {
+        return place;
+    }
+    CPVT_WordPlace newplace = place;
+    newplace.nWordIndex ++;
+    if (m_bRichText) {
+        CPVT_WordProps * pNewProps = pWordProps ? FX_NEW CPVT_WordProps(*pWordProps) : FX_NEW CPVT_WordProps();
+        if (pNewProps) {
+            pNewProps->nFontIndex = GetWordFontIndex(word, charset, pWordProps->nFontIndex);
+            return AddWord(newplace, CPVT_WordInfo(word, charset, -1, pNewProps));
+        }
+    } else {
+        int32_t nFontIndex = GetSubWord() > 0 ? GetDefaultFontIndex() : GetWordFontIndex(word, charset, GetDefaultFontIndex());
+        return AddWord(newplace, CPVT_WordInfo(word, charset, nFontIndex, NULL));
+    }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::InsertSection(const CPVT_WordPlace & place, const CPVT_SecProps * pSecProps,
+        const CPVT_WordProps * pWordProps)
+{
+    int32_t nTotlaWords = this->GetTotalWords();
+    if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {
+        return place;
+    }
+    if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {
+        return place;
+    }
+    if (!m_bMultiLine) {
+        return place;
+    }
+    CPVT_WordPlace wordplace = place;
+    UpdateWordPlace(wordplace);
+    CPVT_WordPlace newplace = place;
+    if (CSection * pSection = m_SectionArray.GetAt(wordplace.nSecIndex)) {
+        CPVT_WordPlace NewPlace(wordplace.nSecIndex + 1, 0, -1);
+        CPVT_SectionInfo secinfo;
+        if (m_bRichText) {
+            if (pSecProps) {
+                secinfo.pSecProps = FX_NEW CPVT_SecProps(*pSecProps);
+            }
+            if (pWordProps) {
+                secinfo.pWordProps = FX_NEW CPVT_WordProps(*pWordProps);
+            }
+        }
+        AddSection(NewPlace, secinfo);
+        newplace = NewPlace;
+        if (CSection * pNewSection = m_SectionArray.GetAt(NewPlace.nSecIndex)) {
+            for (int32_t w = wordplace.nWordIndex + 1, sz = pSection->m_WordArray.GetSize(); w < sz; w++) {
+                if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(w)) {
+                    NewPlace.nWordIndex++;
+                    pNewSection->AddWord(NewPlace, *pWord);
+                }
+            }
+        }
+        ClearSectionRightWords(wordplace);
+    }
+    return newplace;
+}
+CPVT_WordPlace CPDF_VariableText::InsertText(const CPVT_WordPlace & place, FX_LPCWSTR text, int32_t charset,
+        const CPVT_SecProps * pSecProps, const CPVT_WordProps * pProps)
+{
+    CFX_WideString swText = text;
+    CPVT_WordPlace wp = place;
+    for (int32_t i = 0, sz = swText.GetLength(); i < sz; i++) {
+        CPVT_WordPlace oldwp = wp;
+        FX_WORD word = swText.GetAt(i);
+        switch (word) {
+            case 0x0D:
+                if (m_bMultiLine) {
+                    if (swText.GetAt(i + 1) == 0x0A) {
+                        i += 1;
+                    }
+                    wp = InsertSection(wp, pSecProps, pProps);
+                }
+                break;
+            case 0x0A:
+                if (m_bMultiLine) {
+                    if (swText.GetAt(i + 1) == 0x0D) {
+                        i += 1;
+                    }
+                    wp = InsertSection(wp, pSecProps, pProps);
+                }
+                break;
+            case 0x09:
+                word = 0x20;
+            default:
+                wp = InsertWord(wp, word, charset, pProps);
+                break;
+        }
+        if (wp == oldwp) {
+            break;
+        }
+    }
+    return wp;
+}
+CPVT_WordPlace CPDF_VariableText::DeleteWords(const CPVT_WordRange & PlaceRange)
+{
+    FX_BOOL bLastSecPos = FALSE;
+    if (CSection * pSection = m_SectionArray.GetAt(PlaceRange.EndPos.nSecIndex)) {
+        bLastSecPos = (PlaceRange.EndPos == pSection->GetEndWordPlace());
+    }
+    ClearWords(PlaceRange);
+    if (PlaceRange.BeginPos.nSecIndex != PlaceRange.EndPos.nSecIndex) {
+        ClearEmptySections(PlaceRange);
+        if (!bLastSecPos) {
+            LinkLatterSection(PlaceRange.BeginPos);
+        }
+    }
+    return PlaceRange.BeginPos;
+}
+CPVT_WordPlace CPDF_VariableText::DeleteWord(const CPVT_WordPlace & place)
+{
+    return ClearRightWord(AjustLineHeader(place, TRUE));
+}
+CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace & place)
+{
+    return ClearLeftWord(AjustLineHeader(place, TRUE));
+}
+void CPDF_VariableText::SetText(FX_LPCWSTR text, int32_t charset, const CPVT_SecProps * pSecProps,
+                                const CPVT_WordProps * pWordProps)
+{
+    DeleteWords(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
+    CFX_WideString swText = text;
+    CPVT_WordPlace     wp(0, 0, -1);
+    CPVT_SectionInfo secinfo;
+    if (m_bRichText) {
+        if (pSecProps) {
+            secinfo.pSecProps = FX_NEW CPVT_SecProps(*pSecProps);
+        }
+        if (pWordProps) {
+            secinfo.pWordProps = FX_NEW CPVT_WordProps(*pWordProps);
+        }
+    }
+    if (CSection * pSection = m_SectionArray.GetAt(0)) {
+        pSection->m_SecInfo = secinfo;
+    }
+    int32_t nCharCount = 0;
+    for (int32_t i = 0, sz = swText.GetLength(); i < sz; i++) {
+        if (m_nLimitChar > 0 && nCharCount >= m_nLimitChar) {
+            break;
+        }
+        if (m_nCharArray > 0 && nCharCount >= m_nCharArray) {
+            break;
+        }
+        FX_WORD word = swText.GetAt(i);
+        switch (word) {
+            case 0x0D:
+                if (m_bMultiLine) {
+                    if (swText.GetAt(i + 1) == 0x0A) {
+                        i += 1;
+                    }
+                    wp.nSecIndex ++;
+                    wp.nLineIndex = 0;
+                    wp.nWordIndex = -1;
+                    AddSection(wp, secinfo);
+                }
+                break;
+            case 0x0A:
+                if (m_bMultiLine) {
+                    if (swText.GetAt(i + 1) == 0x0D) {
+                        i += 1;
+                    }
+                    wp.nSecIndex ++;
+                    wp.nLineIndex = 0;
+                    wp.nWordIndex = -1;
+                    AddSection(wp, secinfo);
+                }
+                break;
+            case 0x09:
+                word = 0x20;
+            default:
+                wp = InsertWord(wp, word, charset, pWordProps);
+                break;
+        }
+        nCharCount++;
+    }
+}
+void CPDF_VariableText::UpdateWordPlace(CPVT_WordPlace & place) const
+{
+    if (place.nSecIndex < 0) {
+        place = GetBeginWordPlace();
+    }
+    if (place.nSecIndex >= m_SectionArray.GetSize()) {
+        place = GetEndWordPlace();
+    }
+    place = AjustLineHeader(place, TRUE);
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        pSection->UpdateWordPlace(place);
+    }
+}
+int32_t CPDF_VariableText::WordPlaceToWordIndex(const CPVT_WordPlace & place) const
+{
+    CPVT_WordPlace newplace = place;
+    UpdateWordPlace(newplace);
+    int32_t nIndex = 0;
+    int32_t i = 0;
+    int32_t sz = 0;
+    for (i = 0, sz = m_SectionArray.GetSize(); i < sz && i < newplace.nSecIndex; i++) {
+        if (CSection * pSection = m_SectionArray.GetAt(i)) {
+            nIndex += pSection->m_WordArray.GetSize();
+            if (i != m_SectionArray.GetSize() - 1) {
+                nIndex += PVT_RETURN_LENGTH;
+            }
+        }
+    }
+    if (i >= 0 && i < m_SectionArray.GetSize()) {
+        nIndex += newplace.nWordIndex + PVT_RETURN_LENGTH;
+    }
+    return nIndex;
+}
+CPVT_WordPlace CPDF_VariableText::WordIndexToWordPlace(int32_t index) const
+{
+    CPVT_WordPlace place = GetBeginWordPlace();
+    int32_t nOldIndex = 0 , nIndex = 0;
+    FX_BOOL bFind = FALSE;
+    for (int32_t i = 0, sz = m_SectionArray.GetSize(); i < sz; i++) {
+        if (CSection * pSection = m_SectionArray.GetAt(i)) {
+            nIndex += pSection->m_WordArray.GetSize();
+            if (nIndex == index) {
+                place = pSection->GetEndWordPlace();
+                bFind = TRUE;
+                break;
+            } else if (nIndex > index) {
+                place.nSecIndex = i;
+                place.nWordIndex = index - nOldIndex - 1;
+                pSection->UpdateWordPlace(place);
+                bFind = TRUE;
+                break;
+            }
+            if (i != m_SectionArray.GetSize() - 1) {
+                nIndex += PVT_RETURN_LENGTH;
+            }
+            nOldIndex = nIndex;
+        }
+    }
+    if (!bFind) {
+        place = GetEndWordPlace();
+    }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetBeginWordPlace() const
+{
+    return m_bInitial ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace();
+}
+CPVT_WordPlace CPDF_VariableText::GetEndWordPlace() const
+{
+    if (CSection * pSection = m_SectionArray.GetAt(m_SectionArray.GetSize() - 1)) {
+        return pSection->GetEndWordPlace();
+    }
+    return CPVT_WordPlace();
+}
+CPVT_WordPlace CPDF_VariableText::GetPrevWordPlace(const CPVT_WordPlace & place) const
+{
+    if( place.nSecIndex < 0) {
+        return GetBeginWordPlace();
+    }
+    if (place.nSecIndex >= m_SectionArray.GetSize()) {
+        return GetEndWordPlace();
+    }
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        if (place.WordCmp(pSection->GetBeginWordPlace()) <= 0) {
+            if (CSection * pPrevSection = m_SectionArray.GetAt(place.nSecIndex - 1)) {
+                return pPrevSection->GetEndWordPlace();
+            } else {
+                return GetBeginWordPlace();
+            }
+        } else {
+            return pSection->GetPrevWordPlace(place);
+        }
+    }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetNextWordPlace(const CPVT_WordPlace & place) const
+{
+    if (place.nSecIndex < 0) {
+        return GetBeginWordPlace();
+    }
+    if (place.nSecIndex >= m_SectionArray.GetSize()) {
+        return GetEndWordPlace();
+    }
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        if (place.WordCmp(pSection->GetEndWordPlace()) >= 0) {
+            if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
+                return pNextSection->GetBeginWordPlace();
+            } else {
+                return GetEndWordPlace();
+            }
+        } else {
+            return pSection->GetNextWordPlace(place);
+        }
+    }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::SearchWordPlace(const CPDF_Point & point) const
+{
+    CPDF_Point pt = OutToIn(point);
+    CPVT_WordPlace place = GetBeginWordPlace();
+    int32_t nLeft = 0;
+    int32_t nRight = m_SectionArray.GetSize() - 1;
+    int32_t nMid = m_SectionArray.GetSize() / 2;
+    FX_BOOL bUp = TRUE;
+    FX_BOOL bDown = TRUE;
+    while (nLeft <= nRight) {
+        if (CSection * pSection = m_SectionArray.GetAt(nMid)) {
+            if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.top)) {
+                bUp = FALSE;
+            }
+            if (IsFloatBigger(pSection->m_SecInfo.rcSection.bottom, pt.y)) {
+                bDown = FALSE;
+            }
+            if (IsFloatSmaller(pt.y, pSection->m_SecInfo.rcSection.top)) {
+                nRight = nMid - 1;
+                nMid = (nLeft + nRight) / 2;
+                continue;
+            } else if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.bottom)) {
+                nLeft = nMid + 1;
+                nMid = (nLeft + nRight) / 2;
+                continue;
+            } else {
+                place = pSection->SearchWordPlace(
+                            CPDF_Point(pt.x - pSection->m_SecInfo.rcSection.left, pt.y - pSection->m_SecInfo.rcSection.top)
+                        );
+                place.nSecIndex = nMid;
+                return place;
+            }
+        } else {
+            break;
+        }
+    }
+    if (bUp) {
+        place = GetBeginWordPlace();
+    }
+    if (bDown) {
+        place = GetEndWordPlace();
+    }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetUpWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const
+{
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        CPVT_WordPlace temp =  place;
+        CPDF_Point pt = OutToIn(point);
+        if (temp.nLineIndex-- > 0) {
+            return pSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
+        } else {
+            if (temp.nSecIndex-- > 0) {
+                if (CSection * pLastSection = m_SectionArray.GetAt(temp.nSecIndex)) {
+                    temp.nLineIndex = pLastSection->m_LineArray.GetSize() - 1;
+                    return pLastSection->SearchWordPlace(pt.x - pLastSection->m_SecInfo.rcSection.left, temp);
+                }
+            }
+        }
+    }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetDownWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const
+{
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        CPVT_WordPlace temp =  place;
+        CPDF_Point pt = OutToIn(point);
+        if (temp.nLineIndex++ < pSection->m_LineArray.GetSize() - 1) {
+            return pSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
+        } else {
+            if (temp.nSecIndex++ < m_SectionArray.GetSize() - 1) {
+                if (CSection * pNextSection = m_SectionArray.GetAt(temp.nSecIndex)) {
+                    temp.nLineIndex = 0;
+                    return pNextSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
+                }
+            }
+        }
+    }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace(const CPVT_WordPlace & place) const
+{
+    return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
+}
+CPVT_WordPlace CPDF_VariableText::GetLineEndPlace(const CPVT_WordPlace & place) const
+{
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex))
+        if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
+            return pLine->GetEndWordPlace();
+        }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace(const CPVT_WordPlace & place) const
+{
+    return CPVT_WordPlace(place.nSecIndex, 0, -1);
+}
+CPVT_WordPlace CPDF_VariableText::GetSectionEndPlace(const CPVT_WordPlace & place) const
+{
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        return pSection->GetEndWordPlace();
+    }
+    return place;
+}
+int32_t CPDF_VariableText::GetTotalWords() const
+{
+    int32_t nTotal = 0;
+    for (int32_t i = 0, sz = m_SectionArray.GetSize(); i < sz; i++)
+        if (CSection * pSection = m_SectionArray.GetAt(i)) {
+            nTotal += (pSection->m_WordArray.GetSize() + PVT_RETURN_LENGTH);
+        }
+    return nTotal - PVT_RETURN_LENGTH;
+}
+void CPDF_VariableText::ResetSectionArray()
+{
+    for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
+        delete m_SectionArray.GetAt(s);
+    }
+    m_SectionArray.RemoveAll();
+}
+CPVT_WordPlace CPDF_VariableText::AddSection(const CPVT_WordPlace & place, const CPVT_SectionInfo & secinfo)
+{
+    if (IsValid() && !m_bMultiLine) {
+        return place;
+    }
+    int32_t nSecIndex = FPDF_MAX(FPDF_MIN(place.nSecIndex, m_SectionArray.GetSize()), 0);
+    CSection* pSection = new CSection(this);
+    pSection->m_SecInfo = secinfo;
+    pSection->SecPlace.nSecIndex = nSecIndex;
+    if (nSecIndex == m_SectionArray.GetSize()) {
+        m_SectionArray.Add(pSection);
+    } else {
+        m_SectionArray.InsertAt(nSecIndex, pSection);
+    }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::AddLine(const CPVT_WordPlace & place, const CPVT_LineInfo & lineinfo)
+{
+    if (m_SectionArray.IsEmpty()) {
+        return place;
+    }
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        return pSection->AddLine(lineinfo);
+    }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
+{
+    if (m_SectionArray.GetSize() <= 0) {
+        return place;
+    }
+    CPVT_WordPlace newplace = place;
+    newplace.nSecIndex = FPDF_MAX(FPDF_MIN(newplace.nSecIndex, m_SectionArray.GetSize() - 1), 0);
+    if (CSection * pSection = m_SectionArray.GetAt(newplace.nSecIndex)) {
+        return pSection->AddWord(newplace, wordinfo);
+    }
+    return place;
+}
+FX_BOOL CPDF_VariableText::GetWordInfo(const CPVT_WordPlace & place, CPVT_WordInfo & wordinfo)
+{
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
+            wordinfo = *pWord;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+FX_BOOL CPDF_VariableText::SetWordInfo(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
+{
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
+            *pWord = wordinfo;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+FX_BOOL CPDF_VariableText::GetLineInfo(const CPVT_WordPlace & place, CPVT_LineInfo & lineinfo)
+{
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
+            lineinfo = pLine->m_LineInfo;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+FX_BOOL CPDF_VariableText::GetSectionInfo(const CPVT_WordPlace & place, CPVT_SectionInfo & secinfo)
+{
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        secinfo = pSection->m_SecInfo;
+        return TRUE;
+    }
+    return FALSE;
+}
+CPDF_Rect CPDF_VariableText::GetContentRect() const
+{
+    return InToOut(CPDF_EditContainer::GetContentRect());
+}
+FX_FLOAT CPDF_VariableText::GetWordFontSize(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
+{
+    return m_bRichText && WordInfo.pWordProps ? (WordInfo.pWordProps->nScriptType == PVTWORD_SCRIPT_NORMAL || bFactFontSize ? WordInfo.pWordProps->fFontSize : WordInfo.pWordProps->fFontSize * PVT_HALF) : GetFontSize();
+}
+int32_t CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo & WordInfo)
+{
+    return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nFontIndex : WordInfo.nFontIndex;
+}
+FX_FLOAT CPDF_VariableText::GetWordWidth(int32_t nFontIndex, FX_WORD Word, FX_WORD SubWord,
+        FX_FLOAT fCharSpace, int32_t nHorzScale,
+        FX_FLOAT fFontSize, FX_FLOAT fWordTail, int32_t nWordStyle)
+{
+    return (GetCharWidth(nFontIndex, Word, SubWord, nWordStyle) * fFontSize * PVT_FONTSCALE + fCharSpace) * nHorzScale * PVT_PERCENT + fWordTail;
+}
+FX_FLOAT CPDF_VariableText::GetWordWidth(const CPVT_WordInfo & WordInfo)
+{
+    return GetWordWidth(GetWordFontIndex(WordInfo), WordInfo.Word, GetSubWord(), GetCharSpace(WordInfo), GetHorzScale(WordInfo),
+                        GetWordFontSize(WordInfo), WordInfo.fWordTail,
+                        WordInfo.pWordProps ? WordInfo.pWordProps->nWordStyle : 0);
+}
+FX_FLOAT CPDF_VariableText::GetLineAscent(const CPVT_SectionInfo & SecInfo)
+{
+    return m_bRichText && SecInfo.pWordProps ? GetFontAscent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :
+           GetFontAscent(GetDefaultFontIndex(), GetFontSize());
+}
+FX_FLOAT CPDF_VariableText::GetLineDescent(const CPVT_SectionInfo & SecInfo)
+{
+    return m_bRichText && SecInfo.pWordProps ? GetFontDescent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :
+           GetFontDescent(GetDefaultFontIndex(), GetFontSize());
+}
+FX_FLOAT CPDF_VariableText::GetFontAscent(int32_t nFontIndex, FX_FLOAT fFontSize)
+{
+    return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * PVT_FONTSCALE;
+}
+FX_FLOAT CPDF_VariableText::GetFontDescent(int32_t nFontIndex, FX_FLOAT fFontSize)
+{
+    return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * PVT_FONTSCALE;
+}
+FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)
+{
+    return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize);
+}
+FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)
+{
+    return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize);
+}
+FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
+{
+    return GetFontAscent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));
+}
+FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
+{
+    return GetFontDescent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));
+}
+FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo & SecInfo)
+{
+    return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineLeading : m_fLineLeading;
+}
+FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo & SecInfo)
+{
+    return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineIndent : 0.0f;
+}
+int32_t CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo)
+{
+    return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->nAlignment : this->m_nAlignment;
+}
+FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo & WordInfo)
+{
+    return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->fCharSpace : m_fCharSpace;
+}
+int32_t CPDF_VariableText::GetHorzScale(const CPVT_WordInfo & WordInfo)
+{
+    return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nHorzScale : m_nHorzScale;
+}
+void CPDF_VariableText::ClearSectionRightWords(const CPVT_WordPlace & place)
+{
+    CPVT_WordPlace wordplace = AjustLineHeader(place, TRUE);
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        for (int32_t w = pSection->m_WordArray.GetSize() - 1; w > wordplace.nWordIndex; w--) {
+            delete pSection->m_WordArray.GetAt(w);
+            pSection->m_WordArray.RemoveAt(w);
+        }
+    }
+}
+CPVT_WordPlace CPDF_VariableText::AjustLineHeader(const CPVT_WordPlace & place, FX_BOOL bPrevOrNext) const
+{
+    if (place.nWordIndex < 0 && place.nLineIndex > 0) {
+        if (bPrevOrNext) {
+            return GetPrevWordPlace(place);
+        } else {
+            return GetNextWordPlace(place);
+        }
+    }
+    return place;
+}
+FX_BOOL CPDF_VariableText::ClearEmptySection(const CPVT_WordPlace & place)
+{
+    if (place.nSecIndex == 0 && m_SectionArray.GetSize() == 1) {
+        return FALSE;
+    }
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        if (pSection->m_WordArray.GetSize() == 0) {
+            delete pSection;
+            m_SectionArray.RemoveAt(place.nSecIndex);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+void CPDF_VariableText::ClearEmptySections(const CPVT_WordRange & PlaceRange)
+{
+    CPVT_WordPlace wordplace;
+    for (int32_t s = PlaceRange.EndPos.nSecIndex; s > PlaceRange.BeginPos.nSecIndex; s--) {
+        wordplace.nSecIndex = s;
+        ClearEmptySection(wordplace);
+    }
+}
+void CPDF_VariableText::LinkLatterSection(const CPVT_WordPlace & place)
+{
+    CPVT_WordPlace oldplace = AjustLineHeader(place, TRUE);
+    if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
+        if (CSection * pSection = m_SectionArray.GetAt(oldplace.nSecIndex)) {
+            for (int32_t w = 0, sz = pNextSection->m_WordArray.GetSize(); w < sz; w++) {
+                if (CPVT_WordInfo * pWord = pNextSection->m_WordArray.GetAt(w)) {
+                    oldplace.nWordIndex ++;
+                    pSection->AddWord(oldplace, *pWord);
+                }
+            }
+        }
+        delete pNextSection;
+        m_SectionArray.RemoveAt(place.nSecIndex + 1);
+    }
+}
+void CPDF_VariableText::ClearWords(const CPVT_WordRange & PlaceRange)
+{
+    CPVT_WordRange NewRange;
+    NewRange.BeginPos = AjustLineHeader(PlaceRange.BeginPos, TRUE);
+    NewRange.EndPos = AjustLineHeader(PlaceRange.EndPos, TRUE);
+    for (int32_t s = NewRange.EndPos.nSecIndex; s >= NewRange.BeginPos.nSecIndex; s--) {
+        if (CSection * pSection = m_SectionArray.GetAt(s)) {
+            pSection->ClearWords(NewRange);
+        }
+    }
+}
+CPVT_WordPlace CPDF_VariableText::ClearLeftWord(const CPVT_WordPlace & place)
+{
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        CPVT_WordPlace leftplace = this->GetPrevWordPlace(place);
+        if (leftplace != place) {
+            if (leftplace.nSecIndex != place.nSecIndex) {
+                if (pSection->m_WordArray.GetSize() == 0) {
+                    this->ClearEmptySection(place);
+                } else {
+                    this->LinkLatterSection(leftplace);
+                }
+            } else {
+                pSection->ClearWord(place);
+            }
+        }
+        return leftplace;
+    }
+    return place;
+}
+CPVT_WordPlace CPDF_VariableText::ClearRightWord(const CPVT_WordPlace & place)
+{
+    if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+        CPVT_WordPlace rightplace = AjustLineHeader(this->GetNextWordPlace(place), FALSE);
+        if (rightplace != place) {
+            if(rightplace.nSecIndex != place.nSecIndex) {
+                LinkLatterSection(place);
+            } else {
+                pSection->ClearWord(rightplace);
+            }
+        }
+    }
+    return place;
+}
+void CPDF_VariableText::RearrangeAll()
+{
+    Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
+}
+void CPDF_VariableText::RearrangePart(const CPVT_WordRange & PlaceRange)
+{
+    Rearrange(PlaceRange);
+}
+CPVT_FloatRect CPDF_VariableText::Rearrange(const CPVT_WordRange & PlaceRange)
+{
+    CPVT_FloatRect rcRet;
+    if (IsValid()) {
+        if (m_bAutoFontSize) {
+            SetFontSize(GetAutoFontSize());
+            rcRet = RearrangeSections(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
+        } else {
+            rcRet = RearrangeSections(PlaceRange);
+        }
+    }
+    SetContentRect(rcRet);
+    return rcRet;
+}
+FX_FLOAT CPDF_VariableText::GetAutoFontSize()
+{
+    int32_t nTotal = sizeof(gFontSizeSteps) / sizeof(uint8_t);
+    if (IsMultiLine()) {
+        nTotal /= 4;
+    }
+    if (nTotal <= 0) {
+        return 0;
+    }
+    if (GetPlateWidth() <= 0) {
+        return 0;
+    }
+    int32_t nLeft = 0;
+    int32_t nRight = nTotal - 1;
+    int32_t nMid = nTotal / 2;
+    while (nLeft <= nRight) {
+        if (IsBigger(gFontSizeSteps[nMid])) {
+            nRight = nMid - 1;
+            nMid = (nLeft + nRight) / 2;
+            continue;
+        } else {
+            nLeft = nMid + 1;
+            nMid = (nLeft + nRight) / 2;
+            continue;
+        }
+    }
+    return (FX_FLOAT)gFontSizeSteps[nMid];
+}
+FX_BOOL        CPDF_VariableText::IsBigger(FX_FLOAT fFontSize)
+{
+    FX_BOOL bBigger =  FALSE;
+    CPVT_Size szTotal;
+    for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
+        if (CSection * pSection = m_SectionArray.GetAt(s)) {
+            CPVT_Size size = pSection->GetSectionSize(fFontSize);
+            szTotal.x = FPDF_MAX(size.x, szTotal.x);
+            szTotal.y += size.y;
+            if (IsFloatBigger(szTotal.x, GetPlateWidth())
+                    || IsFloatBigger(szTotal.y, GetPlateHeight())
+               ) {
+                bBigger = TRUE;
+                break;
+            }
+        }
+    }
+    return bBigger;
+}
+CPVT_FloatRect CPDF_VariableText::RearrangeSections(const CPVT_WordRange & PlaceRange)
+{
+    CPVT_WordPlace place;
+    FX_FLOAT fPosY = 0;
+    FX_FLOAT fOldHeight;
+    int32_t nSSecIndex = PlaceRange.BeginPos.nSecIndex;
+    int32_t nESecIndex = PlaceRange.EndPos.nSecIndex;
+    CPVT_FloatRect rcRet;
+    for (int32_t s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
+        place.nSecIndex = s;
+        if (CSection * pSection = m_SectionArray.GetAt(s)) {
+            pSection->SecPlace = place;
+            CPVT_FloatRect rcSec = pSection->m_SecInfo.rcSection;
+            if (s >= nSSecIndex) {
+                if (s <= nESecIndex) {
+                    rcSec = pSection->Rearrange();
+                    rcSec.top += fPosY;
+                    rcSec.bottom += fPosY;
+                } else {
+                    fOldHeight = pSection->m_SecInfo.rcSection.bottom - pSection->m_SecInfo.rcSection.top;
+                    rcSec.top = fPosY;
+                    rcSec.bottom = fPosY + fOldHeight;
+                }
+                pSection->m_SecInfo.rcSection = rcSec;
+                pSection->ResetLinePlace();
+            }
+            if (s == 0) {
+                rcRet = rcSec;
+            } else {
+                rcRet.left = FPDF_MIN(rcSec.left, rcRet.left);
+                rcRet.top = FPDF_MIN(rcSec.top, rcRet.top);
+                rcRet.right = FPDF_MAX(rcSec.right, rcRet.right);
+                rcRet.bottom = FPDF_MAX(rcSec.bottom, rcRet.bottom);
+            }
+            fPosY += rcSec.Height();
+        }
+    }
+    return rcRet;
+}
+int32_t CPDF_VariableText::GetCharWidth(int32_t nFontIndex, FX_WORD Word, FX_WORD SubWord, int32_t nWordStyle)
+{
+    if (m_pVTProvider) {
+        if (SubWord > 0) {
+            return m_pVTProvider->GetCharWidth(nFontIndex, SubWord, nWordStyle);
+        } else {
+            return m_pVTProvider->GetCharWidth(nFontIndex, Word, nWordStyle);
+        }
+    }
+    return 0;
+}
+int32_t CPDF_VariableText::GetTypeAscent(int32_t nFontIndex)
+{
+    return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
+}
+int32_t CPDF_VariableText::GetTypeDescent(int32_t nFontIndex)
+{
+    return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
+}
+int32_t CPDF_VariableText::GetWordFontIndex(FX_WORD word, int32_t charset, int32_t nFontIndex)
+{
+    return m_pVTProvider ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex) : -1;
+}
+int32_t CPDF_VariableText::GetDefaultFontIndex()
+{
+    return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
+}
+FX_BOOL        CPDF_VariableText::IsLatinWord(FX_WORD word)
+{
+    return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : FALSE;
+}
+IPDF_VariableText_Iterator * CPDF_VariableText::GetIterator()
+{
+    if (!m_pVTIterator) {
+        return m_pVTIterator = FX_NEW CPDF_VariableText_Iterator(this);
+    }
+    return m_pVTIterator;
+}
+IPDF_VariableText_Provider*    CPDF_VariableText::SetProvider(IPDF_VariableText_Provider * pProvider)
+{
+    IPDF_VariableText_Provider* pOld = m_pVTProvider;
+    m_pVTProvider = pProvider;
+    return pOld;
+}
+CPDF_VariableText_Iterator::CPDF_VariableText_Iterator(CPDF_VariableText * pVT):
+    m_CurPos(-1, -1, -1),
+    m_pVT(pVT)
+{
+}
+CPDF_VariableText_Iterator::~CPDF_VariableText_Iterator()
+{
+}
+void CPDF_VariableText_Iterator::SetAt(int32_t nWordIndex)
+{
+    ASSERT(m_pVT != NULL);
+    m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
+}
+void CPDF_VariableText_Iterator::SetAt(const CPVT_WordPlace & place)
+{
+    ASSERT(m_pVT != NULL);
+    m_CurPos = place;
+}
+FX_BOOL        CPDF_VariableText_Iterator::NextWord()
+{
+    ASSERT(m_pVT != NULL);
+    if (m_CurPos == m_pVT->GetEndWordPlace()) {
+        return FALSE;
+    }
+    m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
+    return TRUE;
+}
+FX_BOOL        CPDF_VariableText_Iterator::PrevWord()
+{
+    ASSERT(m_pVT != NULL);
+    if (m_CurPos == m_pVT->GetBeginWordPlace()) {
+        return FALSE;
+    }
+    m_CurPos = m_pVT->GetPrevWordPlace(m_CurPos);
+    return TRUE;
+}
+FX_BOOL        CPDF_VariableText_Iterator::NextLine()
+{
+    ASSERT(m_pVT != NULL);
+    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+        if (m_CurPos.nLineIndex < pSection->m_LineArray.GetSize() - 1) {
+            m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1);
+            return TRUE;
+        } else {
+            if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
+                m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
+                return TRUE;
+            }
+        }
+    }
+    return FALSE;
+}
+FX_BOOL        CPDF_VariableText_Iterator::PrevLine()
+{
+    ASSERT(m_pVT != NULL);
+    if (m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+        if (m_CurPos.nLineIndex > 0) {
+            m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex - 1, -1);
+            return TRUE;
+        } else {
+            if (m_CurPos.nSecIndex > 0) {
+                if (CSection * pLastSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex - 1)) {
+                    m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, pLastSection->m_LineArray.GetSize() - 1, -1);
+                    return TRUE;
+                }
+            }
+        }
+    }
+    return FALSE;
+}
+FX_BOOL        CPDF_VariableText_Iterator::NextSection()
+{
+    ASSERT(m_pVT != NULL);
+    if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
+        m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
+        return TRUE;
+    }
+    return FALSE;
+}
+FX_BOOL        CPDF_VariableText_Iterator::PrevSection()
+{
+    ASSERT(m_pVT != NULL);
+    if (m_CurPos.nSecIndex > 0) {
+        m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, 0, -1);
+        return TRUE;
+    }
+    return FALSE;
+}
+FX_BOOL        CPDF_VariableText_Iterator::GetWord(CPVT_Word & word) const
+{
+    ASSERT(m_pVT != NULL);
+    word.WordPlace = m_CurPos;
+    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+        if (pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
+            if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
+                word.Word = pWord->Word;
+                word.nCharset = pWord->nCharset;
+                word.fWidth = m_pVT->GetWordWidth(*pWord);
+                word.ptWord = m_pVT->InToOut(
+                                  CPDF_Point(pWord->fWordX + pSection->m_SecInfo.rcSection.left,
+                                             pWord->fWordY + pSection->m_SecInfo.rcSection.top) );
+                word.fAscent = m_pVT->GetWordAscent(*pWord);
+                word.fDescent = m_pVT->GetWordDescent(*pWord);
+                if (pWord->pWordProps) {
+                    word.WordProps = *pWord->pWordProps;
+                }
+                word.nFontIndex = m_pVT->GetWordFontIndex(*pWord);
+                word.fFontSize = m_pVT->GetWordFontSize(*pWord);
+                return TRUE;
+            }
+        }
+    }
+    return FALSE;
+}
+FX_BOOL        CPDF_VariableText_Iterator::SetWord(const CPVT_Word & word)
+{
+    ASSERT(m_pVT != NULL);
+    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+        if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
+            if (pWord->pWordProps) {
+                *pWord->pWordProps = word.WordProps;
+            }
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+FX_BOOL        CPDF_VariableText_Iterator::GetLine(CPVT_Line & line) const
+{
+    ASSERT(m_pVT != NULL);
+    line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);
+    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+        if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
+            line.ptLine = m_pVT->InToOut(
+                              CPDF_Point(pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left,
+                                         pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top) );
+            line.fLineWidth = pLine->m_LineInfo.fLineWidth;
+            line.fLineAscent = pLine->m_LineInfo.fLineAscent;
+            line.fLineDescent = pLine->m_LineInfo.fLineDescent;
+            line.lineEnd = pLine->GetEndWordPlace();
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+FX_BOOL        CPDF_VariableText_Iterator::GetSection(CPVT_Section & section) const
+{
+    ASSERT(m_pVT != NULL);
+    section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1);
+    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+        section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection);
+        if (pSection->m_SecInfo.pSecProps) {
+            section.SecProps = *pSection->m_SecInfo.pSecProps;
+        }
+        if (pSection->m_SecInfo.pWordProps) {
+            section.WordProps = *pSection->m_SecInfo.pWordProps;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+FX_BOOL        CPDF_VariableText_Iterator::SetSection(const CPVT_Section & section)
+{
+    ASSERT(m_pVT != NULL);
+    if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+        if (pSection->m_SecInfo.pSecProps) {
+            *pSection->m_SecInfo.pSecProps = section.SecProps;
+        }
+        if (pSection->m_SecInfo.pWordProps) {
+            *pSection->m_SecInfo.pWordProps = section.WordProps;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}