Fix #i120928: Import Graphic Bullets of MS Word Document

* sw/inc/numrule.hxx
* sw/source/core/doc/number.cxx
* sw/source/filter/ww8/attributeoutputbase.hxx
* sw/source/filter/ww8/escher.hxx
* sw/source/filter/ww8/rtfattributeoutput.cxx
* sw/source/filter/ww8/rtfattributeoutput.hxx
* sw/source/filter/ww8/rtfexport.hxx
* sw/source/filter/ww8/rtfexport.cxx
* sw/source/filter/ww8/writerhelper.cxx
* sw/source/filter/ww8/writerhelper.hxx
* sw/source/filter/ww8/wrtw8esh.cxx
* sw/source/filter/ww8/wrtw8nds.cxx
* sw/source/filter/ww8/wrtw8num.cxx
* sw/source/filter/ww8/wrtww8.cxx
* sw/source/filter/ww8/wrtww8.hxx
* sw/source/filter/ww8/wrtww8gr.cxx
* sw/source/filter/ww8/ww8attributeoutput.hxx
* sw/source/filter/ww8/ww8par.cxx
* sw/source/filter/ww8/ww8par.hxx
* sw/source/filter/ww8/ww8par3.cxx
* sw/source/ui/wrtsh/wrtsh1.cxx

Graphic Bullets Fidelity

Patch by: chengjh,<chengjh@apache.org>
Found by: chengjh,<chengjh@apache.org>
Review by: Fan Zheng,<zheng.easyfan@gmail.com>
Conflicts:
	sw/inc/numrule.hxx
	sw/source/filter/ww8/writerhelper.cxx
	sw/source/filter/ww8/wrtw8nds.cxx

Change-Id: I7b00590a9f05da745678b5ba99b6f6f4e870d197
Signed-off-by: Cedric Bosdonnat <cedric.bosdonnat.ooo@free.fr>
Signed-off-by: Fridrich Strba <fridrich.strba@bluewin.ch>
diff --git a/sw/inc/numrule.hxx b/sw/inc/numrule.hxx
index 562b7a9..4ae7151 100644
--- a/sw/inc/numrule.hxx
+++ b/sw/inc/numrule.hxx
@@ -49,7 +49,8 @@
class SW_DLLPUBLIC SwNumFmt : public SvxNumberFormat, public SwClient
{
    SwFmtVertOrient* pVertOrient;

    //For i120928,record the cp info of graphic within bullet
    sal_Unicode     cGrfBulletCP;
    SW_DLLPRIVATE void UpdateNumNodes( SwDoc* pDoc );
    SW_DLLPRIVATE virtual void NotifyGraphicArrived();

@@ -74,6 +75,11 @@
    SwCharFmt* GetCharFmt() const { return (SwCharFmt*)GetRegisteredIn(); }
    void SetCharFmt( SwCharFmt* );

    //For i120928,access the cp info of graphic within bullet
    void            SetGrfBulletCP(sal_Unicode cP){cGrfBulletCP = cP;}
    sal_Unicode     GetGrfBulletCP()const {return cGrfBulletCP;}
    void ForgetCharFmt();

    virtual void            SetCharFmtName(const String& rSet);
    virtual const String&   GetCharFmtName()const;

diff --git a/sw/source/core/doc/number.cxx b/sw/source/core/doc/number.cxx
index dd8b966..7dd9b3d 100644
--- a/sw/source/core/doc/number.cxx
+++ b/sw/source/core/doc/number.cxx
@@ -178,6 +178,7 @@
    SvxNumberFormat(SVX_NUM_ARABIC),
    SwClient( 0 ),
    pVertOrient(new SwFmtVertOrient( 0, text::VertOrientation::NONE))
    ,cGrfBulletCP(USHRT_MAX)//For i120928,record the cp info of graphic within bullet
{
}

@@ -185,6 +186,7 @@
    SvxNumberFormat(rFmt),
    SwClient( rFmt.GetRegisteredInNonConst() ),
    pVertOrient(new SwFmtVertOrient( 0, rFmt.GetVertOrient()))
    ,cGrfBulletCP(rFmt.cGrfBulletCP)//For i120928,record the cp info of graphic within bullet
{
    sal_Int16 eMyVertOrient = rFmt.GetVertOrient();
    SetGraphicBrush( rFmt.GetBrush(), &rFmt.GetGraphicSize(),
@@ -265,6 +267,8 @@
        rNumFmt.GetRegisteredInNonConst()->Add( this );
    else if( GetRegisteredIn() )
        GetRegisteredInNonConst()->Remove( this );
    //For i120928,record the cp info of graphic within bullet
    cGrfBulletCP = rNumFmt.cGrfBulletCP;
    return *this;
}

diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx
index d340dda..a009162 100644
--- a/sw/source/filter/ww8/attributeoutputbase.hxx
+++ b/sw/source/filter/ww8/attributeoutputbase.hxx
@@ -329,7 +329,8 @@
        sal_Int16 nIndentAt,
        sal_Int16 nFirstLineIndex,
        sal_Int16 nListTabPos,
        const String &rNumberingString ) = 0;
        const String &rNumberingString,
        const SvxBrushItem* pBrush = 0) = 0; // #i120928 export graphic of bullet

protected:

diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 1b8da73..2ca1fc1 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -3199,7 +3199,8 @@
        sal_Int16 nIndentAt,
        sal_Int16 nFirstLineIndex,
        sal_Int16 nListTabPos,
        const String &rNumberingString )
        const String &rNumberingString,
        const SvxBrushItem* )
{
    m_pSerializer->startElementNS( XML_w, XML_lvl,
            FSNS( XML_w, XML_ilvl ), OString::valueOf( sal_Int32( nLevel ) ).getStr(),
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index eb12e56..94edd1b 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -267,7 +267,8 @@
        sal_Int16 nIndentAt,
        sal_Int16 nFirstLineIndex,
        sal_Int16 nListTabPos,
        const String &rNumberingString );
        const String &rNumberingString,
        const SvxBrushItem* pBrush = 0 );

    void WriteField_Impl( const SwField* pFld, ww::eField eType, const String& rFldCmd, sal_uInt8 nMode );
    void WriteFormData_Impl( const ::sw::mark::IFieldmark& rFieldmark );
diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx
index 56399e6..79ec117 100644
--- a/sw/source/filter/ww8/docxexport.hxx
+++ b/sw/source/filter/ww8/docxexport.hxx
@@ -108,6 +108,8 @@

    virtual void AppendBookmark( const rtl::OUString& rName, bool bSkip = false );

    virtual void ExportGrfBullet(const SwTxtNode&) {}

    /// Returns the relationd id
    rtl::OString AddRelation( const rtl::OUString& rType, const rtl::OUString& rTarget );

diff --git a/sw/source/filter/ww8/escher.hxx b/sw/source/filter/ww8/escher.hxx
index c7761a0..4adf3d8 100644
--- a/sw/source/filter/ww8/escher.hxx
+++ b/sw/source/filter/ww8/escher.hxx
@@ -116,6 +116,8 @@
public:
    SwBasicEscherEx(SvStream* pStrm, WW8Export& rWrt);
    sal_Int32 WriteGrfFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId);
    //For i120928,to export graphic of bullet
    sal_Int32 WriteGrfBullet(const Graphic&);
    sal_Int32 WriteOLEFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId);
    void WriteEmptyFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId);
    virtual void WriteFrmExtraData(const SwFrmFmt&);
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx
index 1e2b1b6..8d4eefa 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -1325,7 +1325,8 @@
        sal_Int16 nIndentAt,
        sal_Int16 nFirstLineIndex,
        sal_Int16 /*nListTabPos*/,
        const String &rNumberingString )
        const String &rNumberingString,
        const SvxBrushItem* pBrush)
{
    SAL_INFO("sw.rtf", OSL_THIS_FUNC);

diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx
index aefa724..1d66350 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.hxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.hxx
@@ -202,7 +202,8 @@
        sal_Int16 nIndentAt,
        sal_Int16 nFirstLineIndex,
        sal_Int16 nListTabPos,
        const String &rNumberingString );
        const String &rNumberingString,
        const SvxBrushItem* pBrush = 0);//For i120928,to export graphic of bullet

    void WriteField_Impl( const SwField* pFld, ww::eField eType, const String& rFldCmd, sal_uInt8 nMode );
    void WriteBookmarks_Impl( std::vector< rtl::OUString >& rStarts, std::vector< rtl::OUString >& rEnds );
diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx
index 34073be..e421ac0 100644
--- a/sw/source/filter/ww8/rtfexport.cxx
+++ b/sw/source/filter/ww8/rtfexport.cxx
@@ -168,6 +168,12 @@
    m_pAttrOutput->WriteBookmarks_Impl(aStarts, aEnds);
}

//For i120928,to export graphic of bullet for RTF filter
void RtfExport::ExportGrfBullet(const SwTxtNode& rNd)
{
    //This is for RTF filter on the graphic bullets
}

void RtfExport::WriteChar( sal_Unicode )
{
    SAL_INFO("sw.rtf", OSL_THIS_FUNC);
diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx
index 8fc8e26..1b15c51 100644
--- a/sw/source/filter/ww8/rtfexport.hxx
+++ b/sw/source/filter/ww8/rtfexport.hxx
@@ -73,6 +73,9 @@

    virtual void AppendBookmark( const rtl::OUString& rName, bool bSkip = false );

    //For i120928,add an interface to export graphic of bullet
    virtual void ExportGrfBullet(const SwTxtNode& rNd);

    virtual void WriteCR( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner = ww8::WW8TableNodeInfoInner::Pointer_t()*/ ) { /* no-op for rtf, most probably should not even be in MSWordExportBase */ }
    virtual void WriteChar( sal_Unicode );

diff --git a/sw/source/filter/ww8/writerhelper.cxx b/sw/source/filter/ww8/writerhelper.cxx
index 31f6d89..df5f5ef 100644
--- a/sw/source/filter/ww8/writerhelper.cxx
+++ b/sw/source/filter/ww8/writerhelper.cxx
@@ -49,6 +49,13 @@
#include <fchrfmt.hxx>           //SwFmtCharFmt
#include <unotools/streamwrap.hxx>
#include <numrule.hxx>
#include <vcl/svapp.hxx>//For i120928
#ifdef DEBUGDUMP
#  include <vcl/svapp.hxx>
#  include <tools/urlobj.hxx>
#  include <unotools/ucbstreamhelper.hxx>
#  include <unotools/localfilehelper.hxx>
#endif

using namespace com::sun::star;
using namespace nsSwGetPoolIdFromName;
@@ -149,6 +156,32 @@

namespace sw
{
    //For i120928,size conversion before exporting graphic of bullet
    Frame::Frame(const Graphic&rGrf, const SwPosition &rPos)
        :mpFlyFrm(NULL),
        maPos(rPos),
        maSize(),
        maLayoutSize(),
        mpStartFrameContent(0),
        mbIsInline(true),
        meWriterType(eBulletGrf),
        maGrf(rGrf),
        mbForBullet(true)
    {
        const MapMode aMap100mm( MAP_100TH_MM );
        Size    aSize( rGrf.GetPrefSize() );
        if ( MAP_PIXEL == rGrf.GetPrefMapMode().GetMapUnit() )
        {
            aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap100mm );
        }
        else
        {
            aSize = OutputDevice::LogicToLogic( aSize,rGrf.GetPrefMapMode(), aMap100mm );
        }
        maSize = aSize;
        maLayoutSize = maSize;
    }

    Frame::Frame(const SwFrmFmt &rFmt, const SwPosition &rPos)
        : mpFlyFrm(&rFmt),
          maPos(rPos),
@@ -158,6 +191,9 @@
          mpStartFrameContent(0),
          // #i43447# - move to initialization list
          mbIsInline( (rFmt.GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
          // #i120928# - handle graphic of bullet within existing implementation
          ,maGrf()
          ,mbForBullet(false)
    {
        switch (rFmt.Which())
        {
diff --git a/sw/source/filter/ww8/writerhelper.hxx b/sw/source/filter/ww8/writerhelper.hxx
index d15f2b8..266af14 100644
--- a/sw/source/filter/ww8/writerhelper.hxx
+++ b/sw/source/filter/ww8/writerhelper.hxx
@@ -95,7 +95,7 @@
    class Frame
    {
    public:
        enum WriterSource {eTxtBox, eGraphic, eOle, eDrawing, eFormControl};
        enum WriterSource {eTxtBox, eGraphic, eOle, eDrawing, eFormControl,eBulletGrf};//For i120928,add Grf Bul Type
    private:
        const SwFrmFmt* mpFlyFrm;
        SwPosition maPos;
@@ -108,9 +108,12 @@
        WriterSource meWriterType;
        const SwNode *mpStartFrameContent;
        bool mbIsInline;
        bool mbForBullet:1;
        Graphic maGrf;
    public:
        Frame(const SwFrmFmt &rFlyFrm, const SwPosition &rPos);

    Frame(const Graphic&, const SwPosition &);
    //End
        /** Get the writer SwFrmFmt that this object describes

            @return
@@ -164,6 +167,8 @@
         the first node of content in the frame, might not be any at all.
        */
        const SwNode *GetContent() const { return mpStartFrameContent; }
    const Graphic &GetGraphic() const { return maGrf; }
    bool HasGraphic() const { return mbForBullet; }


        /** Does this sw::Frame refer to the same writer content as another
@@ -173,7 +178,12 @@
        */
        bool RefersToSameFrameAs(const Frame &rOther) const
        {
        if (mbForBullet && rOther.mbForBullet)
            return (maGrf == rOther.maGrf);
        else if ((!mbForBullet) && (!rOther.mbForBullet))
            return (mpFlyFrm == rOther.mpFlyFrm);
        else
            return false;
        }

        /** The Size of the contained element
diff --git a/sw/source/filter/ww8/wrtw8esh.cxx b/sw/source/filter/ww8/wrtw8esh.cxx
index 3d9caf3..d0f8fa9 100644
--- a/sw/source/filter/ww8/wrtw8esh.cxx
+++ b/sw/source/filter/ww8/wrtw8esh.cxx
@@ -1328,6 +1328,57 @@
    }
    return nFlags;
}
//For i120928,this function is added to export graphic of bullet
sal_Int32 SwBasicEscherEx::WriteGrfBullet(const Graphic& rGrf)
{
    OpenContainer( ESCHER_SpContainer );
    AddShape(ESCHER_ShpInst_PictureFrame, 0xa00,0x401);
    EscherPropertyContainer aPropOpt;
    GraphicObject aGraphicObject( rGrf );
    OString aUniqueId = aGraphicObject.GetUniqueID();
    if ( !aUniqueId.isEmpty() )
    {
        const MapMode aMap100mm( MAP_100TH_MM );
        Size    aSize( rGrf.GetPrefSize() );
        if ( MAP_PIXEL == rGrf.GetPrefMapMode().GetMapUnit() )
        {
            aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap100mm );
        }
        else
        {
            aSize = OutputDevice::LogicToLogic( aSize,rGrf.GetPrefMapMode(), aMap100mm );
        }
        Point aEmptyPoint = Point();
        Rectangle aRect( aEmptyPoint, aSize );
        sal_uInt32 nBlibId = mxGlobal->GetBlibID( *(mxGlobal->QueryPictureStream()), aUniqueId,aRect, NULL, 0 );
        if (nBlibId)
            aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
    }
    aPropOpt.AddOpt( ESCHER_Prop_pibFlags, ESCHER_BlipFlagDefault );
    aPropOpt.AddOpt( ESCHER_Prop_dyTextTop, DrawModelToEmu(0));
    aPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, DrawModelToEmu(0));
    aPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, DrawModelToEmu(0));
    aPropOpt.AddOpt( ESCHER_Prop_dxTextRight, DrawModelToEmu(0));
    aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
    aPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
    aPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
    aPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
    aPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
    const Color aTmpColor( COL_WHITE );
    SvxBrushItem aBrush( aTmpColor, RES_BACKGROUND );
    const SvxBrushItem *pRet = rWrt.GetCurrentPageBgBrush();
    if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
        aBrush = *pRet;
    WriteBrushAttr(aBrush, aPropOpt);

    aPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0 );
    aPropOpt.Commit( GetStream() );
    AddAtom(4, ESCHER_ClientAnchor);
    GetStream() << (sal_uInt32)0x80000000;
    CloseContainer();

    return 0;
}

sal_Int32 SwBasicEscherEx::WriteGrfFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
{
@@ -1982,6 +2033,7 @@
                    WriteOCXControl(rFmt, nShapeId = GenerateShapeId());
                    break;
                case sw::Frame::eDrawing:
                {
                    aWinwordAnchoring.SetAnchoring(rFmt);
                    const SdrObject* pSdrObj = rFmt.FindRealSdrObject();
                    if (pSdrObj)
@@ -2009,6 +2061,10 @@
                        OSL_ENSURE( !this, "Where is the SDR-Object?" );
#endif
                }
                break;
                default:
                    break;
            }

            if( !nShapeId )
            {
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 30998e2..f7742d3 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -1734,6 +1734,16 @@

    ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo( mpTableInfo->getTableNodeInfo( &rNode ) );

    //For i120928,identify the last node
    bool bLastCR = false;
    bool bExported = false;
    {
        SwNodeIndex aNextIdx(rNode,1);
        SwNodeIndex aLastIdx(rNode.GetNodes().GetEndOfContent());
        if (aNextIdx == aLastIdx)
            bLastCR = true;
    }

    AttrOutput().StartParagraph( pTextNodeInfo );

    bool bFlyInTable = mpParentFrame && IsInTable();
@@ -1967,6 +1977,13 @@
                        m_aCurrentCharPropStarts.pop();
                        AttrOutput().EndTOX( *pTOXSect );
                    }
            //For i120928,the position of the bullet's graphic is at end of doc
            if (bLastCR && (!bExported))
            {
                ExportGrfBullet(rNode);
                bExported = true;
            }

                    WriteCR( pTextNodeInfoInner );
                }
            }
@@ -2003,6 +2020,13 @@
                aAttrIter.OutFlys( nEnd );
                // insert final bookmarks if any before CR and after flys
                AppendBookmarks( rNode, nEnd, 1 );
                WriteCR( pTextNodeInfoInner );
                // #i120928 - position of the bullet's graphic is at end of doc
                if (bLastCR && (!bExported))
                {
                    ExportGrfBullet(rNode);
                    bExported = true;
                }

                if ( pTOXSect )
                {
diff --git a/sw/source/filter/ww8/wrtw8num.cxx b/sw/source/filter/ww8/wrtw8num.cxx
index d67ca74..4d086b8 100644
--- a/sw/source/filter/ww8/wrtw8num.cxx
+++ b/sw/source/filter/ww8/wrtw8num.cxx
@@ -196,7 +196,8 @@
        sal_Int16 nIndentAt,
        sal_Int16 nFirstLineIndex,
        sal_Int16 nListTabPos,
        const String &rNumberingString
        const String &rNumberingString,
        const SvxBrushItem* pBrush //For i120928,to transfer graphic of bullet
    )
{
    // Start value
@@ -254,6 +255,18 @@
        }

        m_rWW8Export.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rWW8Export.mbExportModeRTF );
    //For i120928,achieve graphic's index of bullet from the bullet bookmark
    if (SVX_NUM_BITMAP == nNumberingType && pBrush)
    {
        int nIndex = m_rWW8Export.GetGrfIndex(*pBrush);
        if ( nIndex != -1 )
        {
            m_rWW8Export.InsUInt16(0x6887);
            m_rWW8Export.InsUInt32(nIndex);
            m_rWW8Export.InsUInt16(0x4888);
            m_rWW8Export.InsUInt16(1);
        }
    }

        m_rWW8Export.pO = pOldpO;
    }
@@ -479,7 +492,8 @@
                    nFollow,
                    pPseudoFont, pOutSet,
                    nIndentAt, nFirstLineIndex, nListTabPos,
                    sNumStr );
                    sNumStr,
                    rFmt.GetNumberingType()==SVX_NUM_BITMAP ? rFmt.GetBrush():0);//Start for i120928,export graphic bullet,2012.9.25

            delete pPseudoFont;
        }
diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
index 1da26f0..9bce330 100644
--- a/sw/source/filter/ww8/wrtww8.cxx
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -109,7 +109,9 @@
#include <rtl/random.h>
#include "WW8Sttbf.hxx"
#include "WW8FibData.hxx"

#ifndef _NUMRULE_HXX
#include "numrule.hxx"//For i120928
#endif
using namespace sw::util;
using namespace sw::types;

@@ -1404,6 +1406,125 @@
    pBkmks->Append( nSttCP, rName );
}

// #i120928 collect all the graphics of bullets applied to paragraphs
int WW8Export::CollectGrfsOfBullets() const
{
    m_vecBulletPic.clear();

    if ( pDoc )
    {
        int nCountRule = pDoc->GetNumRuleTbl().size();
        for (int n = 0; n < nCountRule; ++n)
            {
            const SwNumRule &rRule = *( pDoc->GetNumRuleTbl().at(n) );
            sal_uInt16 nLevels = rRule.IsContinusNum() ? 1 : 9;
            for (sal_uInt16 nLvl = 0; nLvl < nLevels; ++nLvl)
                {
                        const SwNumFmt &rFmt = rRule.Get(nLvl);
                if (SVX_NUM_BITMAP != rFmt.GetNumberingType())
                {
                    continue;
                }
                const Graphic *pGraf = rFmt.GetBrush()? rFmt.GetBrush()->GetGraphic():0;
                if ( pGraf )
                {
                    bool bHas = false;
                    for (unsigned i = 0; i < m_vecBulletPic.size(); ++i)
                    {
                        if (m_vecBulletPic[i]->GetChecksum() == pGraf->GetChecksum())
                        {
                            bHas = true;
                            break;
                        }
                    }
                    if (!bHas)
                    {
                        m_vecBulletPic.push_back(pGraf);
                    }
                }
            }
        }
    }

    return m_vecBulletPic.size();
}
//Export Graphic of Bullets
void WW8Export::ExportGrfBullet(const SwTxtNode& rNd)
{
    int nCount = CollectGrfsOfBullets();
    if (nCount > 0)
    {
        SwPosition aPos(rNd);
        OUString aPicBullets("_PictureBullets");
        AppendBookmark(aPicBullets);
        for (int i = 0; i < nCount; i++)
        {
            sw::Frame aFrame(*(m_vecBulletPic[i]), aPos);
            OutGrfBullets(aFrame);
        }
        AppendBookmark(aPicBullets);
    }
}

static sal_uInt8 nAttrMagicIdx = 0;
void WW8Export::OutGrfBullets(const sw::Frame & rFrame)
{
    if ( !pGrf || !pChpPlc || !pO )
        return;

    pGrf->Insert(rFrame);
    pChpPlc->AppendFkpEntry( Strm().Tell(), pO->size(), pO->data() );
    pO->clear();
    //if links...
    WriteChar( (char)1 );

    sal_uInt8 aArr[ 22 ];
    sal_uInt8* pArr = aArr;

    // sprmCFSpec
    if( bWrtWW8 )
        Set_UInt16( pArr, 0x855 );
    else
        Set_UInt8( pArr, 117 );
    Set_UInt8( pArr, 1 );

    Set_UInt16( pArr, 0x083c );
    Set_UInt8( pArr, 0x81 );

    // sprmCPicLocation
    if( bWrtWW8 )
        Set_UInt16( pArr, 0x6a03 );
    else
    {
        Set_UInt8( pArr, 68 );
        Set_UInt8( pArr, 4 );
    }
    Set_UInt32( pArr, GRF_MAGIC_321 );

    //extern  nAttrMagicIdx;
    --pArr;
    Set_UInt8( pArr, nAttrMagicIdx++ );
    pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
}
//Achieve the index position
int WW8Export::GetGrfIndex(const SvxBrushItem& rBrush)
{
    int nIndex = -1;
    if ( rBrush.GetGraphic() )
    {
        for (unsigned i = 0; i < m_vecBulletPic.size(); ++i)
        {
            if (m_vecBulletPic[i]->GetChecksum() == rBrush.GetGraphic()->GetChecksum())
            {
                nIndex = i;
                break;
            }
        }
    }

    return nIndex;
}

void MSWordExportBase::AppendWordBookmark( const String& rName )
{
    AppendBookmark( BookmarkToWord( rName ) );
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 1763a95..66d402d 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -38,6 +38,9 @@
#include "../inc/msfilter.hxx"
#include <expfld.hxx>

#include <vcl/graph.hxx>
class SvxBrushItem;

// einige Forward Deklarationen
class SwWW8AttrIter;
namespace msfilter
@@ -643,6 +646,8 @@
    virtual void AppendBookmarks( const SwTxtNode& rNd, xub_StrLen nAktPos, xub_StrLen nLen ) = 0;

    virtual void AppendBookmark( const rtl::OUString& rName, bool bSkip = false ) = 0;
    //For i120928,add this interface to export graphic of bullet
    virtual void ExportGrfBullet(const SwTxtNode& rNd) = 0;

    // FIXME probably a hack...
    virtual void WriteCR( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner = ww8::WW8TableNodeInfoInner::Pointer_t() ) = 0;
@@ -907,6 +912,9 @@

    sal_uInt8 bWrtWW8 : 1;                   ///< Write WW95 (false) or WW97 (true) file format

        //For i120928,this vector is to record all the graphics of bullets
    mutable std::vector<const Graphic*> m_vecBulletPic;

protected:
    SwWW8Writer        *m_pWriter;      ///< Pointer to the writer
    WW8AttributeOutput *m_pAttrOutput;  ///< Converting attributes to stream data
@@ -1000,6 +1008,12 @@

    virtual void AppendBookmarks( const SwTxtNode& rNd, xub_StrLen nAktPos, xub_StrLen nLen );
    virtual void AppendBookmark( const rtl::OUString& rName, bool bSkip = false );

    virtual void ExportGrfBullet(const SwTxtNode& rNd);
    int CollectGrfsOfBullets() const;
    void OutGrfBullets(const sw::Frame &rFrame);
    int GetGrfIndex(const SvxBrushItem& rBrush);

    void MoveFieldMarks(sal_uLong nFrom, sal_uLong nTo);

    void WriteAsStringTable(const ::std::vector<rtl::OUString>&, sal_Int32& rfcSttbf,
@@ -1335,6 +1349,9 @@
    void WriteGrfFromGrfNode(SvStream& rStrm, const SwGrfNode &rNd,
        const sw::Frame &rFly, sal_uInt16 nWidth, sal_uInt16 nHeight);

    void WritePICBulletFHeader(SvStream& rStrm, const Graphic &rGrf, sal_uInt16 mm, sal_uInt16 nWidth, sal_uInt16 nHeight);
    void WriteGrfForBullet(SvStream& rStrm,  const Graphic &rGrf, sal_uInt16 nWidth, sal_uInt16 nHeight);

    //No copying
    SwWW8WrGrf(const SwWW8WrGrf&);
    SwWW8WrGrf& operator=(const SwWW8WrGrf&);
diff --git a/sw/source/filter/ww8/wrtww8gr.cxx b/sw/source/filter/ww8/wrtww8gr.cxx
index 4ff1cc4..d7cd88c 100644
--- a/sw/source/filter/ww8/wrtww8gr.cxx
+++ b/sw/source/filter/ww8/wrtww8gr.cxx
@@ -716,6 +716,135 @@
        }
    }
}
//For i120928,export graphic info of bullet
void SwWW8WrGrf::WritePICBulletFHeader(SvStream& rStrm, const Graphic &rGrf,
            sal_uInt16 mm, sal_uInt16 nWidth, sal_uInt16 nHeight)
{
    sal_Int16 nXSizeAdd = 0, nYSizeAdd = 0;
    sal_Int16 nCropL = 0, nCropR = 0, nCropT = 0, nCropB = 0;

    Size aGrTwipSz(rGrf.GetPrefSize());
    bool bWrtWW8 = rWrt.bWrtWW8;
    sal_uInt16 nHdrLen = bWrtWW8 ? 0x44 : 0x3A;

    sal_uInt8 aArr[ 0x44 ] = { 0 };

    sal_uInt8* pArr = aArr + 0x2E;  //Do borders first

    sal_uInt8 aLnArr[4] = { BOX_LINE_TOP, BOX_LINE_LEFT,
    BOX_LINE_BOTTOM, BOX_LINE_RIGHT };
    for( sal_uInt8 i = 0; i < 4; ++i )
    {
        WW8_BRC aBrc;

        short nSpacing;
        short nThick = aBrc.DetermineBorderProperties(!bWrtWW8,
        &nSpacing);
        switch (aLnArr[ i ])
        {
            case BOX_LINE_TOP:
            case BOX_LINE_BOTTOM:
            nHeight -= nThick;
            nHeight = nHeight - nSpacing;
            break;
            case BOX_LINE_LEFT:
            case BOX_LINE_RIGHT:
            default:
            nWidth -= nThick;
            nWidth = nWidth - nSpacing;
            break;
        }
        memcpy( pArr, &aBrc.aBits1, 2);
        pArr+=2;

        if( bWrtWW8 )
        {
            memcpy( pArr, &aBrc.aBits2, 2);
            pArr+=2;
        }
    }

    pArr = aArr + 4;                                //skip lcb
    Set_UInt16( pArr, nHdrLen );                    // set cbHeader

    Set_UInt16( pArr, mm );                         // set mm

    if ( (aGrTwipSz.Width() * 254L / 144 > USHRT_MAX) || (aGrTwipSz.Height()  * 254L / 144 > USHRT_MAX)
        || (aGrTwipSz.Width() < 0 ) || (aGrTwipSz.Height() < 0) )
    {
        aGrTwipSz.Width() = nWidth;
        aGrTwipSz.Height() = nHeight;
    }
    using namespace sw::types;
    // set xExt & yExt
    Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Width() * 254L / 144));
    Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Height() * 254L / 144));
    pArr += 16;
    // skip hMF & rcWinMF
    // set dxaGoal & dyaGoal
    Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Width()));
    Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Height()));

    if( aGrTwipSz.Width() + nXSizeAdd )             // set mx
    {
        double fVal = nWidth * 1000.0 / (aGrTwipSz.Width() + nXSizeAdd);
        Set_UInt16( pArr, (sal_uInt16)::rtl::math::round(fVal) );
    }
    else
        pArr += 2;

    if( aGrTwipSz.Height() + nYSizeAdd )            // set my
    {
        double fVal = nHeight * 1000.0 / (aGrTwipSz.Height() + nYSizeAdd);
        Set_UInt16( pArr, (sal_uInt16)::rtl::math::round(fVal) );
    }
    else
    pArr += 2;

    Set_UInt16( pArr, nCropL );                     // set dxaCropLeft
    Set_UInt16( pArr, nCropT );                     // set dyaCropTop
    Set_UInt16( pArr, nCropR );                     // set dxaCropRight
    Set_UInt16( pArr, nCropB );                     // set dyaCropBottom

    rStrm.Write( aArr, nHdrLen );
}
void SwWW8WrGrf::WriteGrfForBullet(SvStream& rStrm,  const Graphic &rGrf, sal_uInt16 nWidth, sal_uInt16 nHeight)
{
    if (rWrt.bWrtWW8)
    {
        WritePICBulletFHeader(rStrm,rGrf, 0x64,nWidth,nHeight);
        SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
        aInlineEscher.WriteGrfBullet(rGrf);
        aInlineEscher.WritePictures();
    }
    else
    {
        bool bSwapped = rGrf.IsSwapOut() ? true : false;

        GDIMetaFile aMeta;
        switch (rGrf.GetType())
        {
            case GRAPHIC_BITMAP:        // Bitmap -> in Metafile abspielen
            {
                VirtualDevice aVirt;
                aMeta.Record(&aVirt);
                aVirt.DrawBitmap( Point( 0,0 ), rGrf.GetBitmap() );
                aMeta.Stop();
                aMeta.WindStart();
                aMeta.SetPrefMapMode( rGrf.GetPrefMapMode());
                aMeta.SetPrefSize( rGrf.GetPrefSize());
            }
            break;
            case GRAPHIC_GDIMETAFILE :      // GDI ( =SV ) Metafile
                aMeta = rGrf.GetGDIMetaFile();
            break;
            default:
                return;
        }
        WritePICBulletFHeader(rStrm, rGrf, 8, nWidth, nHeight);
        WriteWindowMetafileBits(rStrm, aMeta);
    }
}

void SwWW8WrGrf::WriteGraphicNode(SvStream& rStrm, const GraphicDetails &rItem)
{
@@ -735,6 +864,17 @@
                WriteGrfFromGrfNode(rStrm, *pNd, rItem.maFly, nWidth, nHeight);
        }
        break;
        //For i120928,add branch to export graphic of bullet
        case sw::Frame::eBulletGrf:
        {
        if (rItem.maFly.HasGraphic())
        {
            const Graphic& rGrf = rItem.maFly.GetGraphic();
            WriteGrfForBullet(rStrm, rGrf, nWidth, nHeight);
        }
        }
        break;

        case sw::Frame::eOle:
        {
#ifdef OLE_PREVIEW_AS_EMF
diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx b/sw/source/filter/ww8/ww8attributeoutput.hxx
index 8d1661f..1ebceed 100644
--- a/sw/source/filter/ww8/ww8attributeoutput.hxx
+++ b/sw/source/filter/ww8/ww8attributeoutput.hxx
@@ -190,7 +190,8 @@
        sal_Int16 nIndentAt,
        sal_Int16 nFirstLineIndex,
        sal_Int16 nListTabPos,
        const String &rNumberingString );
        const String &rNumberingString,
        const SvxBrushItem* pBrush = 0); //For i120928,transfer graphic of bullet

protected:
    /// Output frames - the implementation.
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index 463698e..c7104c4 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -34,6 +34,7 @@
#include <comphelper/docpasswordrequest.hxx>
#include <comphelper/string.hxx>

#include <editeng/brushitem.hxx>
#include <editeng/tstpitem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/langitem.hxx>
@@ -85,6 +86,11 @@

#include "writerwordglue.hxx"

#include "ndgrf.hxx"
#include <editeng/editids.hrc>
#include <txtflcnt.hxx>
#include <fmtflcnt.hxx>
#include <txatbase.hxx>

#include "ww8par2.hxx"          // class WW8RStyle, class WW8AnchorPara

@@ -4686,7 +4692,8 @@
    GrafikDtor();
    DELETEZ( pMSDffManager );
    DELETEZ( pHdFt );
    DELETEZ( pLstManager );
    //For i120928,delay the destruct action
    //DELETEZ( pLstManager );
    DELETEZ( pSBase );
    delete pWDop;
    DELETEZ( pFonts );
@@ -4702,6 +4709,84 @@
    delete mpRedlineStack;
    DeleteAnchorStk();
    DeleteRefStks();
    //For i120928,achieve the graphics from the special bookmark with is for graphic bullet
    {
        std::vector<const SwGrfNode*> vecBulletGrf;
        std::vector<SwFrmFmt*> vecFrmFmt;

        IDocumentMarkAccess* const pMarkAccess =
                                                rDoc.getIDocumentMarkAccess();
        if ( pMarkAccess )
        {
                  IDocumentMarkAccess::const_iterator_t ppBkmk =
                                        pMarkAccess->findBookmark( "_PictureBullets" );
                  if ( ppBkmk != pMarkAccess->getBookmarksEnd() &&
                             IDocumentMarkAccess::GetType( *(ppBkmk->get()) )
                                == IDocumentMarkAccess::BOOKMARK )
                    {
                SwTxtNode* pTxtNode = ppBkmk->get()->GetMarkStart().nNode.GetNode().GetTxtNode();
                         if ( pTxtNode )
                {
                    const SwpHints *pHints = pTxtNode->GetpSwpHints();
                    for(int nHintPos = 0; pHints && nHintPos < pHints->Count(); ++nHintPos)
                    {
                        const SwTxtAttr *pHt = (*pHints)[nHintPos];
                        xub_StrLen st = *(pHt->GetStart());
                        if(pHt && pHt->Which() == RES_TXTATR_FLYCNT && (st >= ppBkmk->get()->GetMarkStart().nContent.GetIndex()))
                        {
                            SwFrmFmt *pFrmFmt = pHt->GetFlyCnt().GetFrmFmt();
                            const SwNodeIndex *pNdIdx = pFrmFmt->GetCntnt().GetCntntIdx();
                            const SwNodes &nos = pNdIdx->GetNodes();
                            const SwGrfNode *pGrf = dynamic_cast<const SwGrfNode*>(nos[pNdIdx->GetIndex() + 1]);
                            if (pGrf)
                            {
                                vecBulletGrf.push_back(pGrf);
                                vecFrmFmt.push_back(pFrmFmt);
                            }
                        }
                    }
                    // update graphic bullet information
                    int nCount = pLstManager->GetWW8LSTInfoNum();
                    for (int i = 0; i < nCount; ++i)
                    {
                        SwNumRule* pRule = pLstManager->GetNumRule(i);
                        for (int j = 0; j < MAXLEVEL; ++j)
                        {
                            SwNumFmt aNumFmt(pRule->Get(j));
                            sal_Int16 nType = aNumFmt.GetNumberingType();
                            sal_uInt16 nGrfBulletCP = aNumFmt.GetGrfBulletCP();
                            if (nType == SVX_NUM_BITMAP && vecBulletGrf.size() > nGrfBulletCP)
                            {
                                Graphic aGraphic = vecBulletGrf[nGrfBulletCP]->GetGrf();
                                SvxBrushItem aBrush(aGraphic, GPOS_AREA, SID_ATTR_BRUSH);
                                Font aFont = numfunc::GetDefBulletFont();
                                int nHeight = aFont.GetHeight() * 12;//20;
                                Size aPrefSize( aGraphic.GetPrefSize());
                                if (aPrefSize.Height() * aPrefSize.Width() != 0 )
                                {
                                    int nWidth = (nHeight * aPrefSize.Width()) / aPrefSize.Height();
                                    Size aSize(nWidth, nHeight);
                                    aNumFmt.SetGraphicBrush(&aBrush, &aSize);
                                }
                                else
                                {
                                    aNumFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
                                    aNumFmt.SetBulletChar(0x2190);
                                }
                                pRule->Set( j, aNumFmt );
                            }
                        }
                    }
                    // Remove additional pictures
                    for (sal_uInt16 i = 0; i < vecFrmFmt.size(); ++i)
                    {
                        rDoc.DelLayoutFmt(vecFrmFmt[i]);
                    }
                }
            }
            DELETEZ( pLstManager );
        }
    }

    //remove extra paragraphs after attribute ctrl
    //stacks etc. are destroyed, and before fields
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index f9034e1..0d5da66 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -159,6 +159,8 @@
        std::vector<sal_uInt8> &rParaSprms, SwTxtNode *pNode=0);
    SwNumRule* CreateNextRule(bool bSimple);
    ~WW8ListManager();
    SwNumRule* GetNumRule(int i);
    int GetWW8LSTInfoNum() const{return maLSTInfos.size();}
private:
    wwSprmParser maSprmParser;
    SwWW8ImplReader& rReader;
diff --git a/sw/source/filter/ww8/ww8par3.cxx b/sw/source/filter/ww8/ww8par3.cxx
index 2f0956e..6dfc40f 100644
--- a/sw/source/filter/ww8/ww8par3.cxx
+++ b/sw/source/filter/ww8/ww8par3.cxx
@@ -503,6 +503,9 @@
    SvxExtNumType   eType;              // Writer-Num-Typ
    SvxAdjust       eAdj;               // Ausrichtung (Links/rechts/zent.)
    sal_Unicode     cBullet(0x2190);    // default safe bullet

    sal_Unicode     cGrfBulletCP(USHRT_MAX);

    String          sPrefix;
    String          sPostfix;
    WW8LVL          aLVL;
@@ -642,12 +645,28 @@
    //
    // 3. ggfs. CHPx einlesen und
    //
    sal_uInt16 nWitchPicIsBullet = USHRT_MAX;
    bool bIsPicBullet = false;

    if( aLVL.nLenGrpprlChpx )
    {
        sal_uInt8 aGrpprlChpx[ 255 ];
        memset(&aGrpprlChpx, 0, sizeof( aGrpprlChpx ));
        if(aLVL.nLenGrpprlChpx != rSt.Read(&aGrpprlChpx, aLVL.nLenGrpprlChpx))
            return false;

    //For i120928,parse the graphic info of bullets
    sal_uInt8 *pSprmWhichPis = GrpprlHasSprm(0x6887,aGrpprlChpx[0],aLVL.nLenGrpprlChpx);
    sal_uInt8 *pSprmIsPicBullet = GrpprlHasSprm(0x4888,aGrpprlChpx[0],aLVL.nLenGrpprlChpx);
    if (pSprmWhichPis)
    {
        nWitchPicIsBullet = *pSprmWhichPis;
    }
    if (pSprmIsPicBullet)
    {
        bIsPicBullet = (*pSprmIsPicBullet) & 0x0001;
    }

        // neues ItemSet fuer die Zeichenattribute anlegen
        rpItemSet = new SfxItemSet( rDoc.GetAttrPool(), RES_CHRATR_BEGIN,
            RES_CHRATR_END - 1 );
@@ -717,6 +736,12 @@
        case 23:
        case 25:
            eType = SVX_NUM_CHAR_SPECIAL;
            //For i120928,type info
            if (bIsPicBullet)
            {
                eType = SVX_NUM_BITMAP;
            }

            break;
        case 255:
            eType = SVX_NUM_NUMBER_NONE;
@@ -789,8 +814,10 @@

        if (!cBullet)  // unsave control code?
            cBullet = 0x2190;
    }
    else
    }   else if (SVX_NUM_BITMAP == eType)   //For i120928,position index info of graphic
    {
        cGrfBulletCP = nWitchPicIsBullet;       // This is a bullet picture ID
    } else
    {
        /*
        #i173#
@@ -860,6 +887,11 @@
        // Don't forget: unten, nach dem Bauen eventueller Styles auch noch
        // SetBulletFont() rufen !!!
    }
    //For i120928,position index info
    else if (SVX_NUM_BITMAP == eType)
    {
        rNumFmt.SetGrfBulletCP(cGrfBulletCP);
    }
    else
    {
        // reminder: Garnix ist default Prefix
@@ -1038,6 +1070,14 @@
    return pMyNumRule;
}

SwNumRule* WW8ListManager::GetNumRule(int i)
{
    if ( i >= 0 && i < maLSTInfos.size() )
        return maLSTInfos[i]->pNumRule;
    else
        return 0;
}

// oeffentliche Methoden /////////////////////////////////////////////////////
//
WW8ListManager::WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_)
diff --git a/sw/source/ui/wrtsh/wrtsh1.cxx b/sw/source/ui/wrtsh/wrtsh1.cxx
index 0f3ec52..f1fcdef 100644
--- a/sw/source/ui/wrtsh/wrtsh1.cxx
+++ b/sw/source/ui/wrtsh/wrtsh1.cxx
@@ -268,8 +268,9 @@
        DelRight();
        // eingefuegte Grafik in eigenen Absatz, falls am Ende
        // eines nichtleeren Absatzes
    if ( IsEndPara() && !IsSttPara() )
        SwFEShell::SplitNode();
    //For i120928,avoid to split node
    //if ( IsEndPara() && !IsSttPara() )
    //  SwFEShell::SplitNode();

    EnterSelFrmMode();