// 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 _FX_TEXTBREAK
#define _FX_TEXTBREAK
class IFX_Font;
class CFX_Char;
class IFX_TxtAccess;
class CFX_TxtChar;
class CFX_TxtPiece;
class IFX_TxtBreak;
#define FX_TXTBREAKPOLICY_None				0x00
#define FX_TXTBREAKPOLICY_Pagination		0x01
#define FX_TXTBREAKPOLICY_SpaceBreak		0x02
#define FX_TXTBREAKPOLICY_NumberBreak		0x04
#define FX_TXTBREAK_None					0x00
#define FX_TXTBREAK_PieceBreak				0x01
#define FX_TXTBREAK_LineBreak				0x02
#define FX_TXTBREAK_ParagraphBreak			0x03
#define FX_TXTBREAK_PageBreak				0x04
#define FX_TXTBREAK_ControlChar				0x10
#define FX_TXTBREAK_BreakChar				0x20
#define FX_TXTBREAK_UnknownChar				0x40
#define FX_TXTBREAK_RemoveChar				0x80
#define FX_TXTLAYOUTSTYLE_MutipleFormat		0x0001
#define FX_TXTLAYOUTSTYLE_VerticalLayout	0x0002
#define FX_TXTLAYOUTSTYLE_VerticalChars		0x0004
#define FX_TXTLAYOUTSTYLE_ReverseLine		0x0008
#define FX_TXTLAYOUTSTYLE_ArabicContext		0x0010
#define FX_TXTLAYOUTSTYLE_ArabicShapes		0x0020
#define FX_TXTLAYOUTSTYLE_RTLReadingOrder	0x0040
#define FX_TXTLAYOUTSTYLE_ExpandTab			0x0100
#define FX_TXTLAYOUTSTYLE_SingleLine		0x0200
#define FX_TXTLAYOUTSTYLE_CombText			0x0400
#define FX_TXTCHARSTYLE_Alignment			0x000F
#define FX_TXTCHARSTYLE_ArabicNumber		0x0010
#define FX_TXTCHARSTYLE_ArabicShadda		0x0020
#define FX_TXTCHARSTYLE_OddBidiLevel		0x0040
#define FX_TXTCHARSTYLE_RTLReadingOrder		0x0080
#define FX_TXTCHARSTYLE_ArabicContext		0x0300
#define FX_TXTCHARSTYLE_ArabicIndic			0x0400
#define FX_TXTCHARSTYLE_ArabicComma			0x0800
#define FX_TXTLINEALIGNMENT_Left				0
#define FX_TXTLINEALIGNMENT_Center				1
#define FX_TXTLINEALIGNMENT_Right				2
#define FX_TXTLINEALIGNMENT_Justified			(1 << 2)
#define FX_TXTLINEALIGNMENT_Distributed			(2 << 2)
#define FX_TXTLINEALIGNMENT_JustifiedLeft		(FX_TXTLINEALIGNMENT_Left | FX_TXTLINEALIGNMENT_Justified)
#define FX_TXTLINEALIGNMENT_JustifiedCenter		(FX_TXTLINEALIGNMENT_Center | FX_TXTLINEALIGNMENT_Justified)
#define FX_TXTLINEALIGNMENT_JustifiedRight		(FX_TXTLINEALIGNMENT_Right | FX_TXTLINEALIGNMENT_Justified)
#define FX_TXTLINEALIGNMENT_DistributedLeft		(FX_TXTLINEALIGNMENT_Left | FX_TXTLINEALIGNMENT_Distributed)
#define FX_TXTLINEALIGNMENT_DistributedCenter	(FX_TXTLINEALIGNMENT_Center | FX_TXTLINEALIGNMENT_Distributed)
#define FX_TXTLINEALIGNMENT_DistributedRight	(FX_TXTLINEALIGNMENT_Right | FX_TXTLINEALIGNMENT_Distributed)
#define FX_TXTLINEALIGNMENT_LowerMask			0x03
#define FX_TXTLINEALIGNMENT_HigherMask			0x0C
#define FX_TXTBREAK_MinimumTabWidth				160000
class IFX_TxtAccess
{
public:
    virtual FX_WCHAR	GetChar(FX_LPVOID pIdentity, FX_INT32 index) const = 0;
    virtual FX_INT32	GetWidth(FX_LPVOID pIdentity, FX_INT32 index) const = 0;
};
typedef struct _FX_TXTRUN {
    _FX_TXTRUN()
    {
        pAccess			= NULL;
        pIdentity		= NULL;
        pStr			= NULL;
        pWidths			= NULL;
        iLength			= 0;
        pFont			= NULL;
        fFontSize		= 12;
        dwStyles		= 0;
        iHorizontalScale = 100;
        iVerticalScale	= 100;
        iCharRotation	= 0;
        dwCharStyles	= 0;
        pRect			= NULL;
        wLineBreakChar	= L'\n';
        bSkipSpace		= TRUE;
    }
    IFX_TxtAccess	*pAccess;
    FX_LPVOID		pIdentity;
    FX_LPCWSTR		pStr;
    FX_INT32		*pWidths;
    FX_INT32		iLength;
    IFX_Font		*pFont;
    FX_FLOAT		fFontSize;
    FX_DWORD		dwStyles;
    FX_INT32		iHorizontalScale;
    FX_INT32		iVerticalScale;
    FX_INT32		iCharRotation;
    FX_DWORD		dwCharStyles;
    FX_LPCRECTF		pRect;
    FX_WCHAR		wLineBreakChar;
    FX_BOOL			bSkipSpace;
} FX_TXTRUN, * FX_LPTXTRUN;
typedef FX_TXTRUN const * FX_LPCTXTRUN;
class CFX_TxtPiece : public CFX_Target
{
public:
    CFX_TxtPiece() : m_dwStatus(FX_TXTBREAK_PieceBreak)
        , m_iStartPos(0)
        , m_iWidth(-1)
        , m_iStartChar(0)
        , m_iChars(0)
        , m_iBidiLevel(0)
        , m_iBidiPos(0)
        , m_iHorizontalScale(100)
        , m_iVerticalScale(100)
        , m_dwCharStyles(0)
        , m_pChars(NULL)
        , m_pUserData(NULL)
    {
    }
    FX_INT32 GetEndPos() const
    {
        return m_iWidth < 0 ? m_iStartPos : m_iStartPos + m_iWidth;
    }
    FX_INT32 GetLength() const
    {
        return m_iChars;
    }
    FX_INT32 GetEndChar() const
    {
        return m_iStartChar + m_iChars;
    }
    CFX_TxtChar* GetCharPtr(FX_INT32 index) const
    {
        FXSYS_assert(index > -1 && index < m_iChars && m_pChars != NULL);
        return m_pChars->GetDataPtr(m_iStartChar + index);
    }
    void GetString(FX_LPWSTR pText) const
    {
        FXSYS_assert(pText != NULL);
        FX_INT32 iEndChar = m_iStartChar + m_iChars;
        CFX_Char *pChar;
        for (FX_INT32 i = m_iStartChar; i < iEndChar; i ++) {
            pChar = m_pChars->GetDataPtr(i);
            *pText ++ = (FX_WCHAR)pChar->m_wCharCode;
        }
    }

    void GetString(CFX_WideString &wsText) const
    {
        FX_LPWSTR pText = wsText.GetBuffer(m_iChars);
        GetString(pText);
        wsText.ReleaseBuffer(m_iChars);
    }
    void GetWidths(FX_INT32 *pWidths) const
    {
        FXSYS_assert(pWidths != NULL);
        FX_INT32 iEndChar = m_iStartChar + m_iChars;
        CFX_Char *pChar;
        for (FX_INT32 i = m_iStartChar; i < iEndChar; i ++) {
            pChar = m_pChars->GetDataPtr(i);
            *pWidths ++ = pChar->m_iCharWidth;
        }
    }
    FX_DWORD			m_dwStatus;
    FX_INT32			m_iStartPos;
    FX_INT32			m_iWidth;
    FX_INT32			m_iStartChar;
    FX_INT32			m_iChars;
    FX_INT32			m_iBidiLevel;
    FX_INT32			m_iBidiPos;
    FX_INT32			m_iHorizontalScale;
    FX_INT32			m_iVerticalScale;
    FX_DWORD			m_dwCharStyles;
    CFX_TxtCharArray	*m_pChars;
    FX_LPVOID			m_pUserData;
};
typedef CFX_BaseArrayTemplate<CFX_TxtPiece> CFX_TxtPieceArray;
class IFX_TxtBreak
{
public:
    static IFX_TxtBreak*	Create(FX_DWORD dwPolicies);
    virtual void			Release() = 0;
    virtual void			SetLineWidth(FX_FLOAT fLineWidth) = 0;
    virtual void			SetLinePos(FX_FLOAT fLinePos) = 0;
    virtual FX_DWORD		GetLayoutStyles() const = 0;
    virtual void			SetLayoutStyles(FX_DWORD dwLayoutStyles) = 0;
    virtual void			SetFont(IFX_Font *pFont) = 0;
    virtual void			SetFontSize(FX_FLOAT fFontSize) = 0;
    virtual void			SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant) = 0;
    virtual void			SetDefaultChar(FX_WCHAR wch) = 0;
    virtual void			SetParagraphBreakChar(FX_WCHAR wch) = 0;
    virtual void			SetLineBreakTolerance(FX_FLOAT fTolerance) = 0;
    virtual void			SetHorizontalScale(FX_INT32 iScale) = 0;
    virtual void			SetVerticalScale(FX_INT32 iScale) = 0;
    virtual void			SetCharRotation(FX_INT32 iCharRotation) = 0;
    virtual void			SetCharSpace(FX_FLOAT fCharSpace) = 0;
    virtual void			SetAlignment(FX_INT32 iAlignment) = 0;
    virtual FX_DWORD		GetContextCharStyles() const = 0;
    virtual void			SetContextCharStyles(FX_DWORD dwCharStyles) = 0;
    virtual void			SetCombWidth(FX_FLOAT fCombWidth) = 0;
    virtual void			SetUserData(FX_LPVOID pUserData) = 0;
    virtual FX_DWORD					AppendChar(FX_WCHAR wch) = 0;
    virtual FX_DWORD					EndBreak(FX_DWORD dwStatus = FX_TXTBREAK_PieceBreak) = 0;
    virtual FX_INT32					CountBreakChars() const = 0;
    virtual FX_INT32					CountBreakPieces() const = 0;
    virtual const CFX_TxtPiece*			GetBreakPiece(FX_INT32 index) const = 0;
    virtual void						ClearBreakPieces() = 0;
    virtual void			Reset() = 0;
    virtual FX_INT32		GetDisplayPos(FX_LPCTXTRUN pTxtRun, FXTEXT_CHARPOS *pCharPos, FX_BOOL bCharCode = FALSE, CFX_WideString *pWSForms = NULL, FX_AdjustCharDisplayPos pAdjustPos = NULL) const = 0;
    virtual FX_INT32		GetCharRects(FX_LPCTXTRUN pTxtRun, CFX_RectFArray &rtArray, FX_BOOL bCharBBox = FALSE) const = 0;
};
#endif