// 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

#ifndef CORE_SRC_FPDFDOC_PDF_VT_H_
#define CORE_SRC_FPDFDOC_PDF_VT_H_

class CPVT_Size;
class CPVT_FloatRect;
struct CPVT_SectionInfo;
struct CPVT_LineInfo;
struct CPVT_WordInfo;
class CLine;
class CLines;
class CSection;
class CTypeset;
class CPDF_EditContainer;
class CPDF_VariableText;
class CPDF_VariableText_Iterator;
#define IsFloatZero(f)						((f) < 0.0001 && (f) > -0.0001)
#define IsFloatBigger(fa,fb)				((fa) > (fb) && !IsFloatZero((fa) - (fb)))
#define IsFloatSmaller(fa,fb)				((fa) < (fb) && !IsFloatZero((fa) - (fb)))
template<class T> T FPDF_MIN (const T & i, const T & j)
{
    return ((i < j) ? i : j);
}
template<class T> T FPDF_MAX (const T & i, const T & j)
{
    return ((i > j) ? i : j);
}
class CPVT_Size
{
public:
    CPVT_Size() : x(0.0f), y(0.0f)
    {
    }
    CPVT_Size(FX_FLOAT x, FX_FLOAT y)
    {
        this->x = x;
        this->y = y;
    }
    FX_FLOAT x, y;
};
class CPVT_FloatRect : public CFX_FloatRect
{
public:
    CPVT_FloatRect()
    {
        left = top = right = bottom = 0.0f;
    }
    CPVT_FloatRect(FX_FLOAT left, FX_FLOAT top,
                   FX_FLOAT right, FX_FLOAT bottom)
    {
        this->left = left;
        this->top = top;
        this->right = right;
        this->bottom = bottom;
    }
    CPVT_FloatRect(const CPDF_Rect & rect)
    {
        this->left = rect.left;
        this->top = rect.top;
        this->right = rect.right;
        this->bottom = rect.bottom;
    }
    void Default()
    {
        left = top = right = bottom = 0.0f;
    }
    FX_FLOAT Height() const
    {
        if(this->top > this->bottom) {
            return this->top - this->bottom;
        } else {
            return this->bottom - this->top;
        }
    }
};
struct CPVT_SectionInfo {
    CPVT_SectionInfo() : rcSection(), nTotalLine(0), pSecProps(NULL), pWordProps(NULL)
    {
    }
    virtual ~CPVT_SectionInfo()
    {
        if (pSecProps) {
            delete pSecProps;
        }
        if (pWordProps) {
            delete pWordProps;
        }
    }
    CPVT_SectionInfo(const CPVT_SectionInfo & other): rcSection(), nTotalLine(0), pSecProps(NULL), pWordProps(NULL)
    {
        operator = (other);
    }
    void operator = (const CPVT_SectionInfo & other)
    {
        if (this == &other) {
            return;
        }
        this->rcSection = other.rcSection;
        this->nTotalLine = other.nTotalLine;
        if (other.pSecProps) {
            if (pSecProps) {
                *pSecProps = *other.pSecProps;
            } else {
                pSecProps = FX_NEW CPVT_SecProps(*other.pSecProps);
            }
        }
        if (other.pWordProps) {
            if (pWordProps) {
                *pWordProps = *other.pWordProps;
            } else {
                pWordProps = FX_NEW CPVT_WordProps(*other.pWordProps);
            }
        }
    }
    CPVT_FloatRect				rcSection;
    int32_t					nTotalLine;
    CPVT_SecProps*				pSecProps;
    CPVT_WordProps*				pWordProps;
};
struct CPVT_LineInfo {
    CPVT_LineInfo() : nTotalWord(0), nBeginWordIndex(-1), nEndWordIndex(-1),
        fLineX(0.0f), fLineY(0.0f), fLineWidth(0.0f), fLineAscent(0.0f), fLineDescent(0.0f)
    {
    }
    int32_t					nTotalWord;
    int32_t					nBeginWordIndex;
    int32_t					nEndWordIndex;
    FX_FLOAT					fLineX;
    FX_FLOAT					fLineY;
    FX_FLOAT					fLineWidth;
    FX_FLOAT					fLineAscent;
    FX_FLOAT					fLineDescent;
};
struct CPVT_WordInfo  {
    CPVT_WordInfo() : Word(0), nCharset(0),
        fWordX(0.0f), fWordY(0.0f), fWordTail(0.0f), nFontIndex(-1), pWordProps(NULL)
    {
    }
    CPVT_WordInfo(FX_WORD word, int32_t charset, int32_t fontIndex, CPVT_WordProps * pProps):
        Word(word), nCharset(charset), fWordX(0.0f), fWordY(0.0f), fWordTail(0.0f),
        nFontIndex(fontIndex), pWordProps(pProps)
    {
    }
    virtual ~CPVT_WordInfo()
    {
        if (pWordProps) {
            delete pWordProps;
        }
    }
    CPVT_WordInfo(const CPVT_WordInfo & word): Word(0), nCharset(0),
        fWordX(0.0f), fWordY(0.0f), fWordTail(0.0f), nFontIndex(-1), pWordProps(NULL)
    {
        operator = (word);
    }
    void operator = (const CPVT_WordInfo & word)
    {
        if (this == &word) {
            return;
        }
        this->Word = word.Word;
        this->nCharset = word.nCharset;
        this->nFontIndex = word.nFontIndex;
        if (word.pWordProps) {
            if (pWordProps) {
                *pWordProps = *word.pWordProps;
            } else {
                pWordProps = FX_NEW CPVT_WordProps(*word.pWordProps);
            }
        }
    }
    FX_WORD						Word;
    int32_t					nCharset;
    FX_FLOAT					fWordX;
    FX_FLOAT					fWordY;
    FX_FLOAT					fWordTail;
    int32_t					nFontIndex;
    CPVT_WordProps*				pWordProps;
};
struct CPVT_FloatRange {
    CPVT_FloatRange() : fMin(0.0f), fMax(0.0f)
    {
    }
    CPVT_FloatRange(FX_FLOAT min, FX_FLOAT max) : fMin(min), fMax(max)
    {
    }
    FX_FLOAT Range() const
    {
        return fMax - fMin;
    }
    FX_FLOAT fMin, fMax;
};
template<class TYPE> class CPVT_ArrayTemplate : public CFX_ArrayTemplate<TYPE>
{
public:
    FX_BOOL IsEmpty()
    {
        return CFX_ArrayTemplate<TYPE>::GetSize() <= 0;
    }
    TYPE GetAt(int nIndex) const
    {
        if (nIndex >= 0 && nIndex < CFX_ArrayTemplate<TYPE>::GetSize()) {
            return CFX_ArrayTemplate<TYPE>::GetAt(nIndex);
        }
        return NULL;
    }
    void RemoveAt(int nIndex)
    {
        if (nIndex >= 0 && nIndex < CFX_ArrayTemplate<TYPE>::GetSize()) {
            CFX_ArrayTemplate<TYPE>::RemoveAt(nIndex);
        }
    }
};
class CLine 
{
public:
    CLine();
    virtual ~CLine();
    CPVT_WordPlace							GetBeginWordPlace() const;
    CPVT_WordPlace							GetEndWordPlace() const;
    CPVT_WordPlace							GetPrevWordPlace(const CPVT_WordPlace & place) const;
    CPVT_WordPlace							GetNextWordPlace(const CPVT_WordPlace & place) const;
    CPVT_WordPlace							LinePlace;
    CPVT_LineInfo							m_LineInfo;
};
class CLines
{
public:
    CLines() : m_nTotal(0) {}
    virtual ~CLines()
    {
        RemoveAll();
    }
    int32_t								GetSize() const
    {
        return m_Lines.GetSize();
    }
    CLine *									GetAt(int32_t nIndex) const
    {
        return m_Lines.GetAt(nIndex);
    }
    void									Empty()
    {
        m_nTotal = 0;
    }
    void									RemoveAll()
    {
        for (int32_t i = 0, sz = GetSize(); i < sz; i++) {
            delete GetAt(i);
        }
        m_Lines.RemoveAll();
        m_nTotal = 0;
    }
    int32_t								Add(const CPVT_LineInfo & lineinfo)
    {
        if (m_nTotal >= GetSize()) {
            if (CLine * pLine = FX_NEW CLine) {
                pLine->m_LineInfo = lineinfo;
                m_Lines.Add(pLine);
                return m_nTotal++;
            }
            return m_nTotal;
        } else {
            if (CLine * pLine = GetAt(m_nTotal)) {
                pLine->m_LineInfo = lineinfo;
            }
            return m_nTotal++;
        }
    }
    void									Clear()
    {
        for (int32_t i = GetSize() - 1; i >= m_nTotal; i--) {
            delete GetAt(i);
            m_Lines.RemoveAt(i);
        }
    }
private:
    CPVT_ArrayTemplate<CLine*>				m_Lines;
    int32_t								m_nTotal;
};
class CSection 
{
    friend class CTypeset;
public:
    CSection(CPDF_VariableText * pVT);
    virtual ~CSection();
    void									ResetAll();
    void									ResetLineArray();
    void									ResetWordArray();
    void									ResetLinePlace();
    CPVT_WordPlace							AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo);
    CPVT_WordPlace							AddLine(const CPVT_LineInfo & lineinfo);
    void									ClearWords(const CPVT_WordRange & PlaceRange);
    void									ClearWord(const CPVT_WordPlace & place);
    CPVT_FloatRect							Rearrange();
    CPVT_Size								GetSectionSize(FX_FLOAT fFontSize);
    CPVT_WordPlace							GetBeginWordPlace() const;
    CPVT_WordPlace							GetEndWordPlace() const;
    CPVT_WordPlace							GetPrevWordPlace(const CPVT_WordPlace & place) const;
    CPVT_WordPlace							GetNextWordPlace(const CPVT_WordPlace & place) const;
    void									UpdateWordPlace(CPVT_WordPlace & place) const;
    CPVT_WordPlace							SearchWordPlace(const CPDF_Point & point) const;
    CPVT_WordPlace							SearchWordPlace(FX_FLOAT fx, const CPVT_WordPlace & lineplace) const;
    CPVT_WordPlace							SearchWordPlace(FX_FLOAT fx, const CPVT_WordRange & range) const;
public:
    CPVT_WordPlace							SecPlace;
    CPVT_SectionInfo						m_SecInfo;
    CLines									m_LineArray;
    CPVT_ArrayTemplate<CPVT_WordInfo*>		m_WordArray;
private:
    void									ClearLeftWords(int32_t nWordIndex);
    void									ClearRightWords(int32_t nWordIndex);
    void									ClearMidWords(int32_t nBeginIndex, int32_t nEndIndex);

    CPDF_VariableText						*m_pVT;
};
class CTypeset
{
public:
    CTypeset(CSection * pSection);
    virtual ~CTypeset();
    CPVT_Size								GetEditSize(FX_FLOAT fFontSize);
    CPVT_FloatRect							Typeset();
    CPVT_FloatRect							CharArray();
private:
    void									SplitLines(FX_BOOL bTypeset, FX_FLOAT fFontSize);
    void									OutputLines();

    CPVT_FloatRect							m_rcRet;
    CPDF_VariableText						* m_pVT;
    CSection								* m_pSection;
};
class CPDF_EditContainer
{
public:
    CPDF_EditContainer(): m_rcPlate(0, 0, 0, 0), m_rcContent(0, 0, 0, 0) {};
    virtual ~CPDF_EditContainer() {};
    virtual void							SetPlateRect(const CPDF_Rect & rect)
    {
        m_rcPlate = rect;
    };
    virtual const CPDF_Rect &				GetPlateRect() const
    {
        return m_rcPlate;
    };
    virtual void							SetContentRect(const CPVT_FloatRect & rect)
    {
        m_rcContent = rect;
    };
    virtual CPDF_Rect 						GetContentRect() const
    {
        return m_rcContent;
    };
    FX_FLOAT								GetPlateWidth() const
    {
        return m_rcPlate.right - m_rcPlate.left;
    };
    FX_FLOAT								GetPlateHeight() const
    {
        return m_rcPlate.top - m_rcPlate.bottom;
    };
    CPVT_Size								GetPlateSize() const
    {
        return CPVT_Size(GetPlateWidth(), GetPlateHeight());
    };
    CPDF_Point								GetBTPoint() const
    {
        return CPDF_Point(m_rcPlate.left, m_rcPlate.top);
    };
    CPDF_Point								GetETPoint() const
    {
        return CPDF_Point(m_rcPlate.right, m_rcPlate.bottom);
    };
    inline CPDF_Point						InToOut(const CPDF_Point & point) const
    {
        return CPDF_Point(point.x + GetBTPoint().x, GetBTPoint().y - point.y);
    };
    inline CPDF_Point						OutToIn(const CPDF_Point & point) const
    {
        return CPDF_Point(point.x - GetBTPoint().x, GetBTPoint().y - point.y);
    };
    inline CPDF_Rect						InToOut(const CPVT_FloatRect & rect) const
    {
        CPDF_Point ptLeftTop = InToOut(CPDF_Point(rect.left, rect.top));
        CPDF_Point ptRightBottom = InToOut(CPDF_Point(rect.right, rect.bottom));
        return CPDF_Rect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x, ptLeftTop.y);
    };
    inline CPVT_FloatRect					OutToIn(const CPDF_Rect & rect) const
    {
        CPDF_Point ptLeftTop = OutToIn(CPDF_Point(rect.left, rect.top));
        CPDF_Point ptRightBottom = OutToIn(CPDF_Point(rect.right, rect.bottom));
        return CPVT_FloatRect(ptLeftTop.x, ptLeftTop.y, ptRightBottom.x, ptRightBottom.y);
    };

private:
    CPDF_Rect								m_rcPlate;
    CPVT_FloatRect							m_rcContent;
};
class CPDF_VariableText : public IPDF_VariableText, private CPDF_EditContainer
{
    friend class CTypeset;
    friend class CSection;
    friend class CPDF_VariableText_Iterator;
public:
    CPDF_VariableText();
    virtual ~CPDF_VariableText();
    IPDF_VariableText_Provider*				SetProvider(IPDF_VariableText_Provider * pProvider);
    IPDF_VariableText_Iterator*				GetIterator();
    void									SetPlateRect(const CPDF_Rect & rect)
    {
        CPDF_EditContainer::SetPlateRect(rect);
    }
    void									SetAlignment(int32_t nFormat = 0)
    {
        m_nAlignment = nFormat;
    }
    void									SetPasswordChar(FX_WORD wSubWord = '*')
    {
        m_wSubWord = wSubWord;
    }
    void									SetLimitChar(int32_t nLimitChar = 0)
    {
        m_nLimitChar = nLimitChar;
    }
    void									SetCharSpace(FX_FLOAT fCharSpace = 0.0f)
    {
        m_fCharSpace = fCharSpace;
    }
    void									SetHorzScale(int32_t nHorzScale = 100)
    {
        m_nHorzScale = nHorzScale;
    }
    void									SetMultiLine(FX_BOOL bMultiLine = TRUE)
    {
        m_bMultiLine = bMultiLine;
    }
    void									SetAutoReturn(FX_BOOL bAuto = TRUE)
    {
        m_bLimitWidth = bAuto;
    }
    void									SetFontSize(FX_FLOAT fFontSize)
    {
        m_fFontSize = fFontSize;
    }
    void									SetCharArray(int32_t nCharArray = 0)
    {
        m_nCharArray = nCharArray;
    }
    void									SetAutoFontSize(FX_BOOL bAuto = TRUE)
    {
        m_bAutoFontSize = bAuto;
    }
    void									SetRichText(FX_BOOL bRichText)
    {
        m_bRichText = bRichText;
    }
    void									SetLineLeading(FX_FLOAT fLineLeading)
    {
        m_fLineLeading = fLineLeading;
    }
    void									Initialize();
    FX_BOOL									IsValid() const
    {
        return m_bInitial;
    }
    FX_BOOL									IsRichText() const
    {
        return m_bRichText;
    }
    void									RearrangeAll();
    void									RearrangePart(const CPVT_WordRange & PlaceRange);
    void									ResetAll();
    void									SetText(const FX_WCHAR* text, int32_t charset = 1, const CPVT_SecProps * pSecProps = NULL,
            const CPVT_WordProps * pWordProps = NULL);
    CPVT_WordPlace							InsertWord(const CPVT_WordPlace & place, FX_WORD word, int32_t charset = 1,
            const CPVT_WordProps * pWordProps = NULL);
    CPVT_WordPlace							InsertSection(const CPVT_WordPlace & place, const CPVT_SecProps * pSecProps = NULL,
            const CPVT_WordProps * pWordProps = NULL);
    CPVT_WordPlace							InsertText(const CPVT_WordPlace & place, const FX_WCHAR* text, int32_t charset = 1,
            const CPVT_SecProps * pSecProps = NULL,	const CPVT_WordProps * pWordProps = NULL);
    CPVT_WordPlace							DeleteWords(const CPVT_WordRange & PlaceRange);
    CPVT_WordPlace							DeleteWord(const CPVT_WordPlace & place);
    CPVT_WordPlace							BackSpaceWord(const CPVT_WordPlace & place);
    const CPDF_Rect &						GetPlateRect() const
    {
        return CPDF_EditContainer::GetPlateRect();
    }
    CPDF_Rect								GetContentRect() const;
    int32_t								GetTotalWords() const;
    FX_FLOAT								GetFontSize() const
    {
        return m_fFontSize;
    }
    int32_t								GetAlignment() const
    {
        return m_nAlignment;
    }
    int32_t								GetCharArray() const
    {
        return m_nCharArray;
    }
    int32_t								GetLimitChar() const
    {
        return m_nLimitChar;
    }
    FX_BOOL									IsMultiLine() const
    {
        return m_bMultiLine;
    }
    int32_t								GetHorzScale() const
    {
        return m_nHorzScale;
    }
    FX_FLOAT								GetCharSpace() const
    {
        return m_fCharSpace;
    }

    CPVT_WordPlace							GetBeginWordPlace() const;
    CPVT_WordPlace							GetEndWordPlace() const;
    CPVT_WordPlace							GetPrevWordPlace(const CPVT_WordPlace & place) const;
    CPVT_WordPlace							GetNextWordPlace(const CPVT_WordPlace & place) const;
    CPVT_WordPlace							SearchWordPlace(const CPDF_Point & point) const;
    CPVT_WordPlace							GetUpWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const;
    CPVT_WordPlace							GetDownWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const;
    CPVT_WordPlace							GetLineBeginPlace(const CPVT_WordPlace & place) const;
    CPVT_WordPlace							GetLineEndPlace(const CPVT_WordPlace & place) const;
    CPVT_WordPlace							GetSectionBeginPlace(const CPVT_WordPlace & place) const;
    CPVT_WordPlace							GetSectionEndPlace(const CPVT_WordPlace & place) const;
    void									UpdateWordPlace(CPVT_WordPlace & place) const;
    int32_t								WordPlaceToWordIndex(const CPVT_WordPlace & place) const;
    CPVT_WordPlace							WordIndexToWordPlace(int32_t index) const;
    FX_WORD									GetPasswordChar() const
    {
        return GetSubWord();
    }
    FX_WORD									GetSubWord() const
    {
        return m_wSubWord;
    }
private:
    int32_t								GetCharWidth(int32_t nFontIndex, FX_WORD Word, FX_WORD SubWord, int32_t nWordStyle);
    int32_t								GetTypeAscent(int32_t nFontIndex);
    int32_t								GetTypeDescent(int32_t nFontIndex);
    int32_t								GetWordFontIndex(FX_WORD word, int32_t charset, int32_t nFontIndex);
    int32_t								GetDefaultFontIndex();
    FX_BOOL									IsLatinWord(FX_WORD word);
private:

    CPVT_WordPlace							AddSection(const CPVT_WordPlace & place, const CPVT_SectionInfo & secinfo);
    CPVT_WordPlace							AddLine(const CPVT_WordPlace & place, const CPVT_LineInfo & lineinfo);
    CPVT_WordPlace							AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo);
    FX_BOOL									GetWordInfo(const CPVT_WordPlace & place, CPVT_WordInfo & wordinfo);
    FX_BOOL									SetWordInfo(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo);
    FX_BOOL									GetLineInfo(const CPVT_WordPlace & place, CPVT_LineInfo & lineinfo);
    FX_BOOL									GetSectionInfo(const CPVT_WordPlace & place, CPVT_SectionInfo & secinfo);
    FX_FLOAT								GetWordFontSize(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize = FALSE);
    FX_FLOAT								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);
    FX_FLOAT								GetWordWidth(const CPVT_WordInfo & WordInfo);
    FX_FLOAT								GetWordAscent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize);
    FX_FLOAT								GetWordDescent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize);
    FX_FLOAT								GetWordAscent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize = FALSE);
    FX_FLOAT								GetWordDescent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize = FALSE);
    FX_FLOAT								GetLineAscent(const CPVT_SectionInfo & SecInfo);
    FX_FLOAT								GetLineDescent(const CPVT_SectionInfo & SecInfo);
    FX_FLOAT								GetFontAscent(int32_t nFontIndex, FX_FLOAT fFontSize);
    FX_FLOAT								GetFontDescent(int32_t nFontIndex, FX_FLOAT fFontSize);
    int32_t								GetWordFontIndex(const CPVT_WordInfo & WordInfo);
    FX_FLOAT								GetCharSpace(const CPVT_WordInfo & WordInfo);
    int32_t								GetHorzScale(const CPVT_WordInfo & WordInfo);
    FX_FLOAT								GetLineLeading(const CPVT_SectionInfo & SecInfo);
    FX_FLOAT								GetLineIndent(const CPVT_SectionInfo & SecInfo);
    int32_t								GetAlignment(const CPVT_SectionInfo& SecInfo);

    void									ClearSectionRightWords(const CPVT_WordPlace & place);
    CPVT_WordPlace							AjustLineHeader(const CPVT_WordPlace & place, FX_BOOL bPrevOrNext) const;
    FX_BOOL									ClearEmptySection(const CPVT_WordPlace & place);
    void									ClearEmptySections(const CPVT_WordRange & PlaceRange);
    void									LinkLatterSection(const CPVT_WordPlace & place);
    void									ClearWords(const CPVT_WordRange & PlaceRange);
    CPVT_WordPlace							ClearLeftWord(const CPVT_WordPlace & place);
    CPVT_WordPlace							ClearRightWord(const CPVT_WordPlace & place);
private:
    CPVT_FloatRect							Rearrange(const CPVT_WordRange & PlaceRange);
    FX_FLOAT								GetAutoFontSize();
    FX_BOOL									IsBigger(FX_FLOAT fFontSize);
    CPVT_FloatRect							RearrangeSections(const CPVT_WordRange & PlaceRange);
private:
    void									ResetSectionArray();
private:
    CPVT_ArrayTemplate<CSection*>			m_SectionArray;
    int32_t								m_nLimitChar;
    int32_t								m_nCharArray;
    FX_BOOL									m_bMultiLine;
    FX_BOOL									m_bLimitWidth;
    FX_BOOL									m_bAutoFontSize;
    int32_t								m_nAlignment;
    FX_FLOAT								m_fLineLeading;
    FX_FLOAT								m_fCharSpace;
    int32_t								m_nHorzScale;
    FX_WORD									m_wSubWord;
    FX_FLOAT								m_fFontSize;

private:
    FX_BOOL									m_bInitial;
    FX_BOOL									m_bRichText;
    IPDF_VariableText_Provider *			m_pVTProvider;
    CPDF_VariableText_Iterator *			m_pVTIterator;
};
class CPDF_VariableText_Iterator : public IPDF_VariableText_Iterator
{
public:
    CPDF_VariableText_Iterator(CPDF_VariableText * pVT);
    virtual ~CPDF_VariableText_Iterator();
    FX_BOOL									NextWord();
    FX_BOOL									PrevWord();
    FX_BOOL									NextLine();
    FX_BOOL									PrevLine();
    FX_BOOL									NextSection();
    FX_BOOL									PrevSection();
    FX_BOOL									SetWord(const CPVT_Word & word);
    FX_BOOL									GetWord(CPVT_Word & word) const;
    FX_BOOL									GetLine(CPVT_Line & line) const;
    FX_BOOL									GetSection(CPVT_Section & section) const;
    FX_BOOL									SetSection(const CPVT_Section & section);
    void									SetAt(int32_t nWordIndex);
    void									SetAt(const CPVT_WordPlace & place);
    const CPVT_WordPlace &					GetAt() const
    {
        return m_CurPos;
    };
private:
    CPVT_WordPlace							m_CurPos;
    CPDF_VariableText *						m_pVT;
};

#endif  // CORE_SRC_FPDFDOC_PDF_VT_H_