/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: IBM Corporation
 *
 *  Copyright: 2008 by IBM Corporation
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
/*************************************************************************
 * @file
 *  the class for VO_FrameLayout
 ************************************************************************/
/*************************************************************************
 * Change History
Mar 2005            Created
 ************************************************************************/
#include "lwpframelayout.hxx"
#include "lwppara.hxx"
#include "xfilter/xfstylemanager.hxx"
#include "xfilter/xfparagraph.hxx"
#include "xfilter/xffloatframe.hxx"
#include "xfilter/xfrubystyle.hxx"
#include "lwppagelayout.hxx"
#include "lwpoleobject.hxx"
#include "lwptablelayout.hxx"
#include "lwpgrfobj.hxx"
#include "lwpglobalmgr.hxx"

LwpFrame::LwpFrame(LwpPlacableLayout* pLayout):m_pLayout(pLayout)
{
}

LwpFrame::~LwpFrame()
{
}
/**
* @descr:  parse frame
* @param:  register frame style
* @param:  pFrameStyle - Frame Style object
*
*/
void  LwpFrame::RegisterStyle(XFFrameStyle* pFrameStyle)
{
    ApplyWrapType(pFrameStyle);
    ApplyMargins(pFrameStyle);
    ApplyPadding(pFrameStyle);
    ApplyBorders(pFrameStyle);
    ApplyColumns(pFrameStyle);
    ApplyShadow(pFrameStyle);
    ApplyBackGround(pFrameStyle);
    ApplyWatermark(pFrameStyle);
//  ApplyBackColor(pFrameStyle);
    ApplyProtect(pFrameStyle);
    ApplyTextDir(pFrameStyle);
    ApplyPosType(pFrameStyle);

    pFrameStyle->SetStyleName(m_pLayout->GetName().str());
    XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
    m_StyleName = pXFStyleManager->AddStyle(pFrameStyle).m_pStyle->GetStyleName();
    m_pLayout->SetStyleName(m_StyleName);
}
/**
* @descr:  parse frame and set frame properties
* @param:   pXFFrame - XFFrame object
* @param:  nPageNo - the page number that the frame anchors
*
*/
 void LwpFrame::Parse(XFFrame* pXFFrame, sal_Int32 nPageNo)
 {
    //set the frame style name
    pXFFrame->SetStyleName(m_StyleName);

    //SetAnchorType and position,if it's page anchor,set the page number.
    ParseAnchorType(pXFFrame);
    if(nPageNo>0)
    {
        pXFFrame->SetAnchorPage(nPageNo);
    }

    //Set frame Name
    OUString aFrameName = m_pLayout->GetName().str();
    if(!aFrameName.isEmpty())
    {
        //cause the bug of SODC, the linkframe name can not be "Frame1", so I change the frame name
        /*if(aFrameName.equals("Frame1"))
        {
            aFrameName = "Frame1_COPY";
        }
        pXFFrame->SetName(aFrameName);*/
        pXFFrame->SetName(m_StyleName);
    }

    LwpLayoutGeometry* pLayoutGeo = m_pLayout->GetGeometry();
    //Set frame Width and height
    if(pLayoutGeo)
    {
        double fWidth = m_pLayout->GetWidth();
        double fHeight = m_pLayout->GetHeight();

        pXFFrame->SetWidth( fWidth );
        pXFFrame->SetHeight( fHeight );

        //Get content obj;
        /*LwpObject* pObj =*/ m_pLayout->GetContent().obj();
        if(m_pLayout->IsGroupHead()&&(m_pLayout->IsMinimumHeight()))
        {
            //process grouplayout height. there is problems now
            pXFFrame->SetHeight( fHeight );
        }
        /*
        else if(m_pLayout->IsFitGraphic() && pObj && pObj->GetTag() == VO_GRAPHIC)
        {
            //If is graphic, get original size and set it;
            LwpGraphicObject* pGrpObj = static_cast<LwpGraphicObject*>(pObj);
            long nHeight =0, nWidth =0;
            pGrpObj->GetGrafOrgSize(nWidth, nHeight);
            //add margins to the width and height;
            fWidth = (double)nWidth/TWIPS_PER_CM + m_pLayout->GetMarginsValue(MARGIN_LEFT) + m_pLayout->GetMarginsValue(MARGIN_RIGHT);
            fHeight = (double)nHeight/TWIPS_PER_CM + m_pLayout->GetMarginsValue(MARGIN_TOP) + m_pLayout->GetMarginsValue(MARGIN_BOTTOM);
            pXFFrame->SetWidth(fWidth);
            pXFFrame->SetHeight(fHeight);
        }
        */
        else if(m_pLayout->IsAutoGrow())
        {
            pXFFrame->SetMinHeight( fHeight );
        }
    }

    if(m_pLayout->IsFrame())
    {
        //Set frame link. Only frame layout has this feature
        LwpFrameLayout* pLayout= static_cast<LwpFrameLayout*>(m_pLayout);
        pXFFrame->SetNextLink(pLayout->GetNextLinkName());
    }

 }
/**
* @descr:  parse frame relative to page, frame or cell
* @param:   pCont - content container which contains the frame
*
*/
 void LwpFrame::XFConvert(XFContentContainer* pCont)
 {
     //parse the frame which anchor to page
    LwpVirtualLayout* pParent = m_pLayout->GetParentLayout();
    if(pParent->IsPage()&& pParent->GetParentLayout()->IsPage())
    {
        //for mirror page, problems exist if the parent layout is header or footer layout,
        pParent = pParent->GetParentLayout();
    }
    if(m_pLayout->IsAnchorPage()&& pParent->IsPage())
    {
        //get parent layout
        if(m_pLayout->IsUseOnPage())
        {
            sal_Int32 nPageNo = pParent->GetPageNumber(m_pLayout->GetUsePage());
            if(nPageNo>0)
                m_pLayout->XFConvertFrame(pCont, nPageNo);
        }
        else if(m_pLayout->IsUseOnAllPages())
        {
            sal_Int32 nFirst = pParent->GetPageNumber(FIRST_LAYOUTPAGENO);
            sal_Int32 nLast = pParent->GetPageNumber(LAST_LAYOUTPAGENO);
            if(nLast > 0)
                m_pLayout->XFConvertFrame(pCont, nFirst, nLast, true);

        }
        else if(m_pLayout->IsUseOnAllOddPages()||m_pLayout->IsUseOnAllEvenPages())
        {
            sal_Int32 nFirst = pParent->GetPageNumber(FIRST_LAYOUTPAGENO);
            sal_Int32 nLast = pParent->GetPageNumber(LAST_LAYOUTPAGENO);
            if(nLast > 0)
            {
                sal_uInt16 first = static_cast<sal_uInt16>(nFirst);
                if((m_pLayout->IsUseOnAllOddPages() && !LwpTools::IsOddNumber(first))
                || (m_pLayout->IsUseOnAllEvenPages() && !LwpTools::IsEvenNumber(first)))
                    nFirst++;
                if(nFirst <= nLast)
                {
                    m_pLayout->XFConvertFrame(pCont, nFirst, nLast, false);
                }
            }
        }
    }
    else
    {
        m_pLayout->XFConvertFrame(pCont);
    }

 }
/**
* @descr:  set frame wrap type style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyWrapType(XFFrameStyle *pFrameStyle)
{
    enumXFWrap eWrap = enumXFWrapNone;
    switch(m_pLayout->GetWrapType())
    {
        case LwpPlacableLayout::LAY_WRAP_AROUND:    //fall through
        case LwpPlacableLayout::LAY_WRAP_IRREG_BIGGEST:
        {
            //In SODC, if Optimal wrap type is used and the distance between the frame object
            //and page margins is less than 2cm, the text is not wrapped. While there is no this feature in Word Pro
            //So the optimal wrap type is translated to left side or right side wrap type according to the distance
            //between the frame object and page margins

            eWrap = enumXFWrapBest;
            LwpMiddleLayout* pParent = static_cast<LwpMiddleLayout*>(m_pLayout->GetContainerLayout());
            if(pParent)
            {
                if(IsLeftWider())
                    eWrap = enumXFWrapLeft;
                else
                    eWrap = enumXFWrapRight;
            }
            break;
        }
        case LwpPlacableLayout::LAY_NO_WRAP_BESIDE:
        {
            eWrap = enumXFWrapNone;
            break;
        }
        case LwpPlacableLayout::LAY_NO_WRAP_AROUND:
        {
            eWrap = enumXFWrapRunThrough;
            if(!m_pLayout->GetBackColor() && !m_pLayout->GetWaterMarkLayout())
            {
                //pFrameStyle->SetBackGround(sal_True);
                XFColor aXFColor(0xffffff); //white color
                pFrameStyle->SetBackColor(aXFColor);
                pFrameStyle->SetTransparency(100);  //transparency
            }
            break;
        }
        case LwpPlacableLayout::LAY_WRAP_LEFT:      //fall through
        case LwpPlacableLayout::LAY_WRAP_IRREG_LEFT:
        {
            eWrap = enumXFWrapLeft;
            break;
        }
        case LwpPlacableLayout::LAY_WRAP_RIGHT: //fall through
        case LwpPlacableLayout::LAY_WRAP_IRREG_RIGHT:
        {
            eWrap = enumXFWrapRight;
            break;
        }
        case LwpPlacableLayout::LAY_WRAP_BOTH:  //fall through
        case LwpPlacableLayout::LAY_WRAP_IRREG_BOTH:
        {
            eWrap = enumXFWrapParallel;
            break;
        }
        default:
            break;
    }

    //If it is the type of with para above, wrap type is enumXFWrapNone
    if(m_pLayout->GetRelativeType()==LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE)
    {
        eWrap = enumXFWrapNone;
    }

    pFrameStyle->SetWrapType(eWrap);
}
/**
* @descr:   set frame margins style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyMargins(XFFrameStyle *pFrameStyle)
{
    double fLeft    = m_pLayout->GetExtMarginsValue(MARGIN_LEFT);
    double fRight   = m_pLayout->GetExtMarginsValue(MARGIN_RIGHT);
    double fTop = m_pLayout->GetExtMarginsValue(MARGIN_TOP);
    double fBottom  = m_pLayout->GetExtMarginsValue(MARGIN_BOTTOM);
    pFrameStyle->SetMargins(fLeft,fRight,fTop,fBottom);
}
/**
* @descr:  set padding border style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyPadding(XFFrameStyle *pFrameStyle)
{
    double fLeft    = m_pLayout->GetMarginsValue(MARGIN_LEFT);
    double fRight   = m_pLayout->GetMarginsValue(MARGIN_RIGHT);
    double fTop = m_pLayout->GetMarginsValue(MARGIN_TOP);
    double fBottom  = m_pLayout->GetMarginsValue(MARGIN_BOTTOM);
    pFrameStyle->SetPadding(fLeft,fRight,fTop,fBottom);
}
/**
* @descr:  set frame border style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyBorders(XFFrameStyle *pFrameStyle)
{
    XFBorders* pBordres = m_pLayout->GetXFBorders();
    if(pBordres)
    {
        pFrameStyle->SetBorders(pBordres);
    }
}
/**
* @descr:  set frame columns style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyColumns(XFFrameStyle *pFrameStyle)
{
    XFColumns* pColumns = m_pLayout->GetXFColumns();
    if(pColumns)
    {
        pFrameStyle->SetColumns(pColumns);
    }
}
/**
* @descr:  set frame shadow style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyShadow(XFFrameStyle* pFrameStyle)
{
    XFShadow* pXFShadow = m_pLayout->GetXFShadow();
    if(pXFShadow)
    {
        pFrameStyle->SetShadow(pXFShadow);
    }
}
/**
* @descr:  set frame back color style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyBackColor(XFFrameStyle* pFrameStyle)
{
    LwpColor* pColor = m_pLayout->GetBackColor();
    if(pColor)
    {
        XFColor aXFColor(pColor->To24Color());
        pFrameStyle->SetBackColor(aXFColor);
    }
}
/**
* @descr:  set frame protect style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyProtect(XFFrameStyle* pFrameStyle)
{
    if(m_pLayout->IsProtected())
    {
        pFrameStyle->SetProtect(true,true,true);
    }
}
/**
* @descr:  set frame text direction style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyTextDir(XFFrameStyle* pFrameStyle)
{
    pFrameStyle->SetTextDir(m_pLayout->GetTextDirection());
}
/**
* @descr:  set frame position type style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyPosType(XFFrameStyle* pFrameStyle)
{
    enumXFFrameXPos eXPos = enumXFFrameXPosCenter;
    enumXFFrameXRel eXRel = enumXFFrameXRelPara;
    enumXFFrameYPos eYPos = enumXFFrameYPosMiddle;
    enumXFFrameYRel eYRel = enumXFFrameYRelPara;
    sal_uInt8 nType = m_pLayout->GetRelativeType();
    switch(nType)
    {
        case LwpLayoutRelativityGuts::LAY_PARENT_RELATIVE://fall through
        case LwpLayoutRelativityGuts::LAY_CONTENT_RELATIVE:
        {
            //anchor to page, frame and cell
            eXPos = enumXFFrameXPosFromLeft;
            eXRel = enumXFFrameXRelPage;
            //set vertical position
            if(m_pLayout->IsAnchorPage())//in page
            {
                LwpVirtualLayout* pContainer = m_pLayout->GetContainerLayout();
                if(pContainer && (pContainer->IsHeader() || pContainer->IsFooter()))
                {
                    //Only anchor to para, the frame can display in header and footer of each page
                    eYPos = enumXFFrameYPosFromTop; //from top
                    eYRel = enumXFFrameYRelPara; //from margin
                }
                else
                {
                    eYPos = enumXFFrameYPosFromTop;
                    eYRel = enumXFFrameYRelPage;
                }
            }
            if(m_pLayout->IsAnchorFrame()) //in frame
            {
                eYPos = enumXFFrameYPosFromTop;
                eYRel = enumXFFrameYRelPage;
            }
            if(m_pLayout->IsAnchorCell())
            {
                //SODC has no this type, simulate this feature
                eYPos = enumXFFrameYPosFromTop; //from top
                eYRel = enumXFFrameYRelPara; //from margin
            }
            break;
        }
        case LwpLayoutRelativityGuts::LAY_PARA_RELATIVE:    //same page as text
        {
            eXPos = enumXFFrameXPosFromLeft;
            eXRel = enumXFFrameXRelPage;
            eYPos = enumXFFrameYPosBelow;   //below
            eYRel = enumXFFrameYRelChar; //from char
            //set vertical position
            LwpVirtualLayout* pContainer = m_pLayout->GetContainerLayout();
            if(pContainer && pContainer->IsPage())//in page
            {
                //eYPos = enumXFFrameYPosFromTop;
                //eYRel = enumXFFrameYRelPage;
                eYPos = enumXFFrameYPosBelow;
                eYRel = enumXFFrameYRelChar;
            }
            else if(pContainer && pContainer->IsFrame()) //in frame
            {
                eYPos = enumXFFrameYPosFromTop;
                eYRel = enumXFFrameYRelPage;
            }
            else
            {
                eYPos = enumXFFrameYPosFromTop; //from top
                eYRel = enumXFFrameYRelPara; //from margin
            }
            break;
        }
        case LwpLayoutRelativityGuts::LAY_INLINE:   //in text
        {
            eXPos = enumXFFrameXPosFromLeft;    //need not be set
            eXRel = enumXFFrameXRelParaContent; //need not be set
            eYPos = enumXFFrameYPosTop; //should be from top
            eYRel = enumXFFrameYRelBaseLine;
            sal_Int32 nOffset = m_pLayout->GetBaseLineOffset();
            if(nOffset>0)
            {
                eYPos = enumXFFrameYPosFromTop;
            }
            break;
        }
        case LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE:   //with para above
        {
            eXPos = enumXFFrameXPosFromLeft;
            eXRel = enumXFFrameXRelParaContent;
            //eYPos = enumXFFrameYPosTop;
            eYPos = enumXFFrameYPosBottom;
            eYRel = enumXFFrameYRelParaContent;
            break;
        }
        case LwpLayoutRelativityGuts::LAY_INLINE_VERTICAL:  //in text - vertical
        {
            eXPos = enumXFFrameXPosFromLeft;
            eXRel = enumXFFrameXRelPage;
            eYPos = enumXFFrameYPosFromTop; //should be below position
            eYRel = enumXFFrameYRelChar;
            break;
        }
        default:
            break;
    }

    pFrameStyle->SetXPosType(eXPos,eXRel);
    pFrameStyle->SetYPosType(eYPos,eYRel);
}
/**
* @descr:  set frame watermark style
* @param:  pFrameStyle - Frame Style object
*
*/
void LwpFrame::ApplyWatermark(XFFrameStyle *pFrameStyle)
{
    XFBGImage* pBGImage = m_pLayout->GetXFBGImage();
    if(pBGImage)
    {
        pFrameStyle->SetBackImage(pBGImage);
        //set watermark transparent
         LwpMiddleLayout* pLay = static_cast<LwpMiddleLayout*>(m_pLayout->GetWaterMarkLayout());
         LwpBackgroundStuff* pBackgroundStuff = pLay->GetBackgroundStuff();
         if(pBackgroundStuff && !pBackgroundStuff->IsTransparent())
         {
             pFrameStyle->SetTransparency(100);
         }
     }
}

/**
 * @short   Apply pattern fill to frame style
 * @param pFrameStyle - pointer of XFFrameStyle
 * @return
 */
void LwpFrame::ApplyPatternFill(XFFrameStyle* pFrameStyle)
{
    XFBGImage* pXFBGImage = m_pLayout->GetFillPattern();
    if (pXFBGImage)
    {
        pFrameStyle->SetBackImage(pXFBGImage);
    }
}

/**
 * @short   Apply background to frame style
 * @param pFrameStyle - pointer of XFFrameStyle
 * @return
 */
void LwpFrame::ApplyBackGround(XFFrameStyle* pFrameStyle)
{
    if (!m_pLayout)
    {
        return;
    }

    if (m_pLayout->IsPatternFill())
    {
        ApplyPatternFill(pFrameStyle);
    }
    else
    {
        ApplyBackColor(pFrameStyle);
    }
}

/**
* @descr:  set frame size, anchor type, anchored page number
* @param:  pXFFrame - XFFrame  object
*
*/
void LwpFrame::ParseAnchorType(XFFrame *pXFFrame)
{
    //set position
    double fXOffset = 0;
    double fYOffset = 0;
    //page number
    sal_uInt16 nPageNum = 0;
    //set anchor type
    enumXFAnchor eAnchor = enumXFAnchorNone;

    LwpLayoutGeometry* pLayoutGeo = m_pLayout->GetGeometry();
    if(pLayoutGeo)
    {
        LwpPoint aPoint = pLayoutGeo->GetOrigin();
        fXOffset = LwpTools::ConvertFromUnitsToMetric(aPoint.GetX());
        fYOffset = LwpTools::ConvertFromUnitsToMetric(aPoint.GetY());
    }
    //set anchor type
    eAnchor = enumXFAnchorNone;
    sal_uInt8 nType = m_pLayout->GetRelativeType();
    switch(nType)
    {
        case LwpLayoutRelativityGuts::LAY_PARENT_RELATIVE://fall through
        case LwpLayoutRelativityGuts::LAY_CONTENT_RELATIVE:
        {
            //anchor to page, frame and cell
            if(m_pLayout->IsAnchorPage())//in page
            {
                LwpVirtualLayout* pContainer = m_pLayout->GetContainerLayout();
                if(pContainer && (pContainer->IsHeader() || pContainer->IsFooter()))
                {
                    eAnchor = enumXFAnchorPara;
                    fYOffset -= pContainer->GetMarginsValue(MARGIN_TOP);
                }
                else
                    eAnchor = enumXFAnchorPage;
            }
            if(m_pLayout->IsAnchorFrame()) //in frame
            {
                eAnchor = enumXFAnchorFrame;
            }
            if(m_pLayout->IsAnchorCell())   //in cell
            {
                //eAnchor = enumXFAnchorChar;
                eAnchor = enumXFAnchorPara;
                LwpMiddleLayout* pContainer = static_cast<LwpMiddleLayout*>(m_pLayout->GetContainerLayout());
                if(pContainer)
                {
                    fYOffset -= pContainer->GetMarginsValue(MARGIN_TOP);
                }
            }
            break;
        }
        case LwpLayoutRelativityGuts::LAY_PARA_RELATIVE:    //same page as text
        {
            eAnchor = enumXFAnchorChar;
            LwpVirtualLayout* pContainer = m_pLayout->GetContainerLayout();
            if(pContainer && pContainer->IsPage())//in page
            {
                //eAnchor = enumXFAnchorPage;
                eAnchor = enumXFAnchorChar;// to character
            }
            else if(pContainer && pContainer->IsFrame()) //in frame
            {
                eAnchor = enumXFAnchorFrame;
            }
            else if(pContainer && pContainer->IsCell()) //in cell
            {
                //eAnchor = enumXFAnchorChar;
                eAnchor = enumXFAnchorPara;
                fYOffset -= pContainer->GetMarginsValue(MARGIN_TOP);
            }
            else if(pContainer && (pContainer->IsHeader() || pContainer->IsFooter()))//in header or footer
            {
                eAnchor = enumXFAnchorPara;
                fYOffset -= pContainer->GetMarginsValue(MARGIN_TOP);
            }
            break;
        }
        case LwpLayoutRelativityGuts::LAY_INLINE:   //in text
        {
            eAnchor = enumXFAnchorAsChar;
            sal_Int32 nOffset = m_pLayout->GetBaseLineOffset();
            if(nOffset>0 && pLayoutGeo)
            {
                //experiential value
                fYOffset =-(m_pLayout->GetGeometryHeight()+2*m_pLayout->GetExtMarginsValue(MARGIN_BOTTOM)-LwpTools::ConvertFromUnitsToMetric(nOffset));
            }
            break;
        }
        case LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE:   //with para above
        {
            eAnchor = enumXFAnchorPara;
            break;
        }
        case LwpLayoutRelativityGuts::LAY_INLINE_VERTICAL:  //in text - vertical
        {
            eAnchor = enumXFAnchorChar;
            //set vertical position
            double offset = 0;

            //because of the different feature between Word Pro and SODC, I simulate the vertical base offset
            //between anchor and frame origin using the font height.
            //LwpPara* pPara = static_cast<LwpPara*>(m_pLayout->GetPosition()->obj());
            rtl::Reference<XFFont> pFont = m_pLayout->GetFont();
            if(pFont.is())
            {
                offset = (double)(pFont->GetFontSize())*CM_PER_INCH/POINTS_PER_INCH;
            }
            fYOffset = offset-fYOffset;
            break;
        }
        default:
            break;
    }

    pXFFrame->SetX(fXOffset);
    pXFFrame->SetY(fYOffset);
    pXFFrame->SetAnchorPage(nPageNum);
    pXFFrame->SetAnchorType(eAnchor);
}

/**
 * @descr Calculate the distance between the frame object and the page margins.
 *       And determine which side(left or right) is wider
 */
bool LwpFrame::IsLeftWider()
{
    //LwpMiddleLayout* pParent = static_cast<LwpMiddleLayout*>(m_pLayout->GetContainerLayout());
    LwpVirtualLayout* pParent = static_cast<LwpVirtualLayout*>(m_pLayout->GetContainerLayout());
    if(pParent)
    {
        LwpPoint aPoint = m_pLayout->GetOrigin();
        double fXOffset = LwpTools::ConvertFromUnitsToMetric(aPoint.GetX());
        double fWidth = m_pLayout->GetWidth();
        double fWrapLeft = m_pLayout->GetExtMarginsValue(MARGIN_LEFT);
        double fWrapRight = m_pLayout->GetExtMarginsValue(MARGIN_RIGHT);

        //LwpPoint aParentPoint = pParent->GetOrigin();
        //double fParentXOffset = LwpTools::ConvertFromUnitsToMetric(aParentPoint.GetX());
        double fParentWidth = pParent->GetWidth();
        if(pParent->IsCell())
        {
            //Get actual width of this cell layout
            fParentWidth = static_cast<LwpCellLayout*>(pParent)->GetActualWidth();
        }
        double fParentMarginLeft = pParent->GetMarginsValue(MARGIN_LEFT);
        double fParentMarginRight = pParent->GetMarginsValue(MARGIN_RIGHT);

        double fLeft = fXOffset - fWrapLeft -fParentMarginLeft;
        double fRight = fParentWidth - fParentMarginRight -(fXOffset + fWidth + fWrapRight);
        if(fLeft > fRight)
            return true;
    }
    return false;
}

LwpFrameLink::LwpFrameLink()
{}

LwpFrameLink::~LwpFrameLink()
{}

/**
 * @descr frame link information
 *
 */
void LwpFrameLink::Read(LwpObjectStream* pStrm)
{
    m_PreviousLayout.ReadIndexed(pStrm);
    m_NextLayout.ReadIndexed(pStrm);
    pStrm->SkipExtra();
}

LwpFrameLayout::LwpFrameLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm)
    : LwpPlacableLayout(objHdr, pStrm), m_pFrame(NULL)
{
}

LwpFrameLayout::~LwpFrameLayout()
{
    delete m_pFrame;
}

/**
 * @descr read frame layout object
 *
 */
void LwpFrameLayout::Read()
{
    LwpPlacableLayout::Read();
    if(LwpFileHeader::m_nFileRevision >= 0x000B)
    {
        if(m_pObjStrm->QuickReaduInt16())
        {
            m_Link.Read(m_pObjStrm);
        }
    }
    m_pObjStrm->SkipExtra();
}

/**
 * @descr create a xfframe and add into content container
 * @param:  pCont - content container that contains the frame.
 *
 */
 void LwpFrameLayout::XFConvert(XFContentContainer* pCont)
 {
    if(m_pFrame)
    {
        //parse the frame which anchor to paragraph
        if(IsRelativeAnchored())
        {
            XFConvertFrame(pCont);
        }
        else
        {
            m_pFrame->XFConvert(pCont);
        }

    }
 }
/**
 * @descr create a xfframe and add into content container, called by XFConvert
 * @param:  pCont - content container that contains the frame.
 * @param:  nPageNo - the page number that the frame anchors
 *
 */
void LwpFrameLayout::XFConvertFrame(XFContentContainer* pCont, sal_Int32 nStart , sal_Int32 nEnd, bool bAll )
{
    if(m_pFrame)
    {
        XFFrame* pXFFrame = NULL;
        if(nEnd < nStart)
        {
            pXFFrame = new XFFrame();
        }
        else
        {
            pXFFrame = new XFFloatFrame(nStart, nEnd, bAll);
        }

        m_pFrame->Parse(pXFFrame, nStart);
        //if it is a link frame, parse contents only once
        if(!HasPreviousLinkLayout())
        {
            rtl::Reference<LwpObject> content = m_Content.obj();
            if (content.is())
            {
                content->XFConvert(pXFFrame);
                //set frame size according to ole size
                ApplyGraphicSize(pXFFrame);
            }
        }
        pCont ->Add(pXFFrame);
    }
}
/**
 * @descr register frame style
 *
 */
void  LwpFrameLayout::RegisterStyle()
{
    //if it is for water mark, don't register style
    if (IsForWaterMark())
        return;

    if (m_pFrame)
        return;

    //register frame style
    XFFrameStyle* pFrameStyle = new XFFrameStyle();
    m_pFrame = new LwpFrame(this);
    m_pFrame->RegisterStyle(pFrameStyle);

    //register content style
    rtl::Reference<LwpObject> content = m_Content.obj();
    if (content.is())
    {
        content->SetFoundry(m_pFoundry);
        content->RegisterStyle();
    }

    //register child frame style
    RegisterChildStyle();
}

/**
 * @descr get the name of the frame that current frame links
 *
 */
OUString LwpFrameLayout::GetNextLinkName()
{
    OUString aName;
    LwpObjectID& rObjectID = m_Link.GetNextLayout();
    if(!rObjectID.IsNull())
    {
        LwpLayout* pLayout = dynamic_cast<LwpLayout*>(rObjectID.obj().get());
        if (pLayout)
        {
            LwpAtomHolder& rHolder = pLayout->GetName();
            aName = rHolder.str();
            //for division name confict
            if(!pLayout->GetStyleName().isEmpty())
                aName = pLayout->GetStyleName();
        }
    }
    return aName;
}
/**
 * @descr whether current frame is linked by other frame
 *
 */
bool LwpFrameLayout::HasPreviousLinkLayout()
{
    LwpObjectID& rObjectID = m_Link.GetPreviousLayout();
    if(rObjectID.IsNull())
        return false;
    return true;
}
/**
 * @descr whether current frame is for water mark. Problem maybe exsits by this method, must be tracking
 *
 */
bool LwpFrameLayout::IsForWaterMark()
{
    if(m_nBuoyancy >=LAY_BUOYLAYER)
    {
        if(!m_Content.IsNull() && (m_Content.obj()->GetTag()==VO_GRAPHIC) )
        {
            return true;
        }
    }
    return false;
}

/**
 * @descr Get frame width
 *
 */
double LwpFrameLayout::GetWidth()
{
    double fWidth = LwpMiddleLayout::GetWidth();
    if(IsInlineToMargin() && IsAutoGrowWidth())
    {
        //for text field entry when choosing maximize field length
        fWidth = GetMaxWidth();
    }
    return fWidth;
}

/**
 * @descr Get frame width when the text field chooses maximize field length
 *
 */
double LwpFrameLayout::GetMaxWidth()
{
    double fActualWidth = 0;
    LwpMiddleLayout* pParent = static_cast<LwpMiddleLayout*>(GetContainerLayout());
    if(pParent)
    {
        LwpPoint aPoint = GetOrigin();
        double fXOffset = LwpTools::ConvertFromUnitsToMetric(aPoint.GetX());
        double fWrapRight = GetExtMarginsValue(MARGIN_RIGHT);

        //Get parent layout width
        double fParentWidth = pParent->GetWidth();
        if(pParent->IsCell())
        {
            //Get actual width of this cell layout
            fParentWidth = static_cast<LwpCellLayout*>(pParent)->GetActualWidth();
        }

        double fParentMarginRight = 0;
        sal_uInt8 nType = GetRelativeType();
        if(nType == LwpLayoutRelativityGuts::LAY_INLINE
            || nType == LwpLayoutRelativityGuts::LAY_INLINE_NEWLINE )
        {
            fParentMarginRight = pParent->GetMarginsValue(MARGIN_RIGHT);
        }

        fActualWidth = fParentWidth - fXOffset - fParentMarginRight - fWrapRight;
    }

    return fActualWidth;
}

/**
 * @descr Set frame size according to graphic size
 *
 */
void LwpFrameLayout::ApplyGraphicSize(XFFrame * pXFFrame)
{
    rtl::Reference<LwpObject> content = m_Content.obj();
    if(content.is() && (content->GetTag() == VO_GRAPHIC
                || content->GetTag() == VO_OLEOBJECT ))
    {
        LwpGraphicOleObject* pGraOle = static_cast<LwpGraphicOleObject*>(content.get());
        //Get frame geometry size
        double fWidth = 0;
        double fHeight = 0;
        pGraOle->GetGrafScaledSize(fWidth, fHeight);
        if( IsFitGraphic())
        {
            //graphic scaled sze
            fWidth += GetMarginsValue(MARGIN_LEFT) + GetMarginsValue(MARGIN_RIGHT);
            fHeight += GetMarginsValue(MARGIN_TOP) + GetMarginsValue(MARGIN_BOTTOM);
        }
        else if(IsAutoGrowDown() || IsAutoGrowUp())
        {
            fWidth = GetWidth();
            fHeight += GetMarginsValue(MARGIN_TOP) + GetMarginsValue(MARGIN_BOTTOM);
        }
        else if( IsAutoGrowLeft() || IsAutoGrowRight())
        {
            fHeight = GetHeight();
            fWidth += GetMarginsValue(MARGIN_LEFT) + GetMarginsValue(MARGIN_RIGHT);
        }
        else
        {
            fWidth = GetWidth();
            fHeight = GetHeight();
        }
        pXFFrame->SetWidth(fWidth);
        pXFFrame->SetHeight(fHeight);
    }
}

LwpGroupLayout::LwpGroupLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm)
    : LwpPlacableLayout(objHdr, pStrm)
    , m_pFrame(NULL)
{

}

LwpGroupLayout::~LwpGroupLayout()
{
    delete m_pFrame;
}
/**
 * @descr read group layout object
 *
 */
void LwpGroupLayout::Read()
{
    LwpPlacableLayout::Read();
    m_pObjStrm->SkipExtra();
}
/**
 * @descr register group frame style
 *
 */
void LwpGroupLayout::RegisterStyle()
{
    if (m_pFrame)
        return;

    //register frame style
    XFFrameStyle* pFrameStyle = new XFFrameStyle();
    m_pFrame = new LwpFrame(this);
    m_pFrame->RegisterStyle(pFrameStyle);

    //register child frame style
    RegisterChildStyle();
}
/**
 * @descr create a xfframe and add into content container
 * @param:  pCont - content container that contains the frame.
 *
 */
void LwpGroupLayout::XFConvert(XFContentContainer *pCont)
{
    if(m_pFrame)
    {
        //parse the frame which anchor to paragraph
        if(IsRelativeAnchored())
        {
            XFConvertFrame(pCont);
        }
        else
        {
            m_pFrame->XFConvert(pCont);
        }

    }
}
/**
 * @descr create a xfframe and add into content container, called by XFConvert
 * @param:  pCont - content container that contains the frame.
 * @param:  nPageNo - the page number that the frame anchors
 *
 */
void LwpGroupLayout::XFConvertFrame(XFContentContainer* pCont, sal_Int32 nStart , sal_Int32 nEnd, bool bAll)
{
    if(m_pFrame)
    {
        XFFrame* pXFFrame = NULL;
        if(nEnd < nStart)
        {
            pXFFrame = new XFFrame();
        }
        else
        {
            pXFFrame = new XFFloatFrame(nStart, nEnd, bAll);
        }

        m_pFrame->Parse(pXFFrame, nStart);

        //add child frame into group
        LwpVirtualLayout* pLayout = static_cast<LwpVirtualLayout*>(GetChildHead().obj().get());
        while(pLayout)
        {
            pLayout->XFConvert(pXFFrame);
            pLayout = static_cast<LwpVirtualLayout*>(pLayout->GetNext().obj().get());
        }

        pCont ->Add(pXFFrame);
    }
}

LwpGroupFrame::LwpGroupFrame(LwpObjectHeader &objHdr, LwpSvStream* pStrm)
    :LwpContent(objHdr, pStrm)
{}

LwpGroupFrame::~LwpGroupFrame()
{}

void LwpGroupFrame::Read()
{
    LwpContent::Read();
    m_pObjStrm->SkipExtra();

}

void  LwpGroupFrame::RegisterStyle()
{
}

void LwpGroupFrame::XFConvert(XFContentContainer* /*pCont*/)
{
}

LwpDropcapLayout::LwpDropcapLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm)
    : LwpFrameLayout(objHdr, pStrm)
{
    m_nChars = 1;
    m_nLines = 3;
}

void LwpDropcapLayout::Read()
{
    LwpFrameLayout::Read();
    m_nLines = m_pObjStrm->QuickReaduInt16();
    m_pObjStrm->SeekRel(1);
    m_pObjStrm->SkipExtra();
}

void LwpDropcapLayout::Parse(IXFStream* pOutputStream)
{
    LwpStory* pStory = static_cast<LwpStory*>(m_Content.obj(VO_STORY).get());
    if (!pStory)
        return;
    rtl::Reference<LwpObject> pPara = pStory->GetFirstPara().obj(VO_PARA);
    if(pPara.is())
    {
        pPara->SetFoundry(m_pFoundry);
        pPara->Parse(pOutputStream);
    }
}

void LwpDropcapLayout::XFConvert(XFContentContainer* pCont)
{
    LwpStory* pStory = static_cast<LwpStory*>(m_Content.obj(VO_STORY).get());
    if (pStory)
    {
        pStory->SetFoundry(m_pFoundry);
        pStory->XFConvert(pCont);
    }
}

LwpStory* LwpDropcapLayout::GetContentStory()
{
    return static_cast<LwpStory*>(m_Content.obj(VO_STORY).get());
}

void LwpDropcapLayout::RegisterStyle(LwpFoundry* pFoundry)
{
    LwpStory* pStory = GetContentStory();
    if (pStory)
    {
        pStory->SetDropcapFlag(true);
        pStory->SetFoundry(pFoundry);
        LwpPara* pPara = static_cast<LwpPara*>(pStory->GetFirstPara().obj().get());
        while(pPara)
        {
            pPara->SetFoundry(pFoundry);
            pPara->RegisterStyle();
            pPara = static_cast<LwpPara*>(pPara->GetNext().obj().get());
        }
    }
}

/**
 * @descr  do nothing
 *
 */
void LwpDropcapLayout::RegisterStyle()
{
}

LwpRubyLayout::LwpRubyLayout(LwpObjectHeader &objHdr, LwpSvStream* pStrm)
    : LwpFrameLayout(objHdr, pStrm)
    , m_nPlacement(0)
    , m_nAlignment(0)
    , m_nStateFlag(0)
    , m_nXOffset(0)
    , m_nYOffset(0)
{
}

void LwpRubyLayout::Read()
{
    LwpFrameLayout::Read();
    m_nPlacement = m_pObjStrm->QuickReaduInt8();
    m_nAlignment = m_pObjStrm->QuickReaduInt8();
    m_nStateFlag = m_pObjStrm->QuickReaduInt16();
    m_nXOffset = m_pObjStrm->QuickReadInt32();
    m_nYOffset = m_pObjStrm->QuickReadInt32();
    m_objRubyMarker.ReadIndexed(m_pObjStrm);
    m_pObjStrm->SkipExtra();
}

LwpRubyMarker* LwpRubyLayout::GetMarker()
{
    return static_cast<LwpRubyMarker*>(m_objRubyMarker.obj(VO_RUBYMARKER).get());
}

LwpStory* LwpRubyLayout::GetContentStory()
{
    return static_cast<LwpStory*>(m_Content.obj(VO_STORY).get());
}

void LwpRubyLayout::ConvertContentText()
{
    LwpStory* pStory = GetContentStory();
    LwpRubyMarker* pMarker = GetMarker();
    if (pStory && pMarker)
        pMarker->SetRubyText(pStory->GetContentText(true));
}

void LwpRubyLayout::RegisterStyle()
{
    LwpRubyMarker* pMarker = GetMarker();

    XFRubyStyle* pRubyStyle = new XFRubyStyle;

    enumXFRubyPosition eType = enumXFRubyLeft;
    if (m_nAlignment == LEFT)
    {
        eType = enumXFRubyLeft;
    }
    else if(m_nAlignment == RIGHT)
    {
        eType =  enumXFRubyRight;
    }
    else if(m_nAlignment == CENTER)
    {
        eType =  enumXFRubyCenter;
    }
    pRubyStyle->SetAlignment(eType);

    eType = enumXFRubyTop;
    if (m_nPlacement == TOP)
    {
        eType = enumXFRubyTop;
    }
    else if(m_nPlacement == BOTTOM)
    {
        eType =  enumXFRubyBottom;
    }
    pRubyStyle->SetPosition(eType);

    XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
    OUString rubyStyle = pXFStyleManager->AddStyle(pRubyStyle).m_pStyle->GetStyleName();
    pMarker->SetRubyStyleName(rubyStyle);

    LwpStory* pStory = GetContentStory();
    pStory->SetFoundry(m_pFoundry);
    OUString textStyle = pStory->RegisterFirstFribStyle();
    pMarker->SetTextStyleName(textStyle);
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
