summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8/ww8graf.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/ww8/ww8graf.cxx')
-rw-r--r--sw/source/filter/ww8/ww8graf.cxx3252
1 files changed, 3252 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/ww8graf.cxx b/sw/source/filter/ww8/ww8graf.cxx
new file mode 100644
index 000000000000..ab78cbbc59b1
--- /dev/null
+++ b/sw/source/filter/ww8/ww8graf.cxx
@@ -0,0 +1,3252 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+#include <svl/urihelper.hxx>
+#include <hintids.hxx>
+#include <osl/endian.h>
+#include <svx/fmglob.hxx>
+#include <svx/sdtaitm.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <svx/xlineit.hxx>
+#include <svx/xfillit.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/sdtaitm.hxx>
+#include <svx/svdocapt.hxx>
+#include <svx/sxctitm.hxx>
+#include <editeng/editeng.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdopath.hxx>
+#include <svx/svdocirc.hxx>
+#include <editeng/outlobj.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdoole2.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <svx/svdoattr.hxx>
+#include <editeng/brshitem.hxx>
+#include <svx/rectenum.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/outliner.hxx> // #79453#
+#include <editeng/frmdiritem.hxx>
+#include <svx/xfltrit.hxx>
+#include <filter/msfilter/msdffimp.hxx>
+#include <grfatr.hxx> // class SwCropGrf
+#include <fmtornt.hxx>
+#include <fmtcntnt.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <pam.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <ndgrf.hxx>
+#include <ndtxt.hxx>
+#include <dcontact.hxx>
+#include <docsh.hxx>
+#include <mdiexp.hxx> // Progress
+#include <fmtcnct.hxx>
+#include <swunodef.hxx>
+#include "ww8struc.hxx"
+#include "ww8scan.hxx"
+#include "ww8par.hxx" // class SwWWImplReader
+#include "ww8par2.hxx" // SwWW8StyInf
+#include "ww8graf.hxx"
+#include <fmtinfmt.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/flditem.hxx>
+// OD 30.09.2003 #i18732#
+#include <fmtfollowtextflow.hxx>
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <editeng/editobj.hxx>
+
+#include <math.h>
+
+using namespace ::com::sun::star;
+using namespace sw::types;
+using namespace sw::util;
+
+// Hilfsroutinen
+
+Color WW8TransCol(SVBT32 nWC)
+{
+#if 1 // 1 = Vordefinierte Farben benutzen, 0 = ignorieren
+
+ // Farbtabelle zum Umrechnen RGB-Werte in vordefinierte Farben
+ // ( Damit bei der Writer-UI die Farbnamen stimmen )
+ // Die Tabelle int im *3er-System* aufgeteilt. Die Grauwerte fehlen,
+ // da sie nicht ins 3er-System passen ( 4 Werte: sw, ws, 2 * grau )
+ static ColorData eColA[] = { // B G R B G R B G R
+ COL_BLACK, COL_RED, COL_LIGHTRED, // 0 0 0, 0 0 1, 0 0 2
+ COL_GREEN, COL_BROWN, COL_BLACK, // 0 1 0, 0 1 1, 0 1 2
+ COL_LIGHTGREEN, COL_BLACK, COL_YELLOW, // 0 2 0, 0 2 1, 0 2 2
+ COL_BLUE, COL_MAGENTA, COL_BLACK, // 1 0 0, 1 0 1, 1 0 2
+ COL_CYAN, COL_LIGHTGRAY, COL_BLACK, // 1 1 0, 1 1 1, 1 1 2
+ COL_BLACK, COL_BLACK, COL_BLACK, // 1 2 0, 1 2 1, 1 2 2
+ COL_LIGHTBLUE, COL_BLACK, COL_LIGHTMAGENTA, // 2 0 0, 2 0 1, 2 0 2
+ COL_BLACK, COL_BLACK, COL_BLACK, // 2 1 0, 2 1 1, 2 1 2
+ COL_LIGHTCYAN, COL_BLACK, COL_WHITE }; // 2 2 0, 2 2 1, 2 2 2
+
+ // In nWC[3] steht ein Byte, dass in der WW-Doku nicht beschrieben ist.
+ // Die Bedeutung ist anscheinend folgende: Bei 0 ist es eine normale
+ // Farbe, dessen RGB-Wert in nWC[0..2] steht. stehen in nWC[3] die
+ // Werte 0x1, 0x7d oder 0x83, dann ist es ein Grauwert, dessen
+ // Schwarzanteil in 1/2 % in nWC[0] steht.
+ // Ich vermute, dass es auf Bit0 in nWV[3] ankommt, ob es RGB oder Grau ist.
+
+ if( !( nWC[3] & 0x1 ) && // keine Spezial-Farbe (grau)
+ ( ( nWC[0] == 0 || nWC[0]== 0x80 || nWC[0] == 0xff ) // R-Anteil
+ && ( nWC[1] == 0 || nWC[1]== 0x80 || nWC[1] == 0xff ) // G-Anteil
+ && ( nWC[2] == 0 || nWC[2]== 0x80 || nWC[2] == 0xff ) ) ){// B-Anteil
+ int nIdx = 0; // und nun: Idx-Berechnung im 3er-System
+ for (int i = 2; i >= 0; i--)
+ {
+ nIdx *= 3;
+ if (nWC[i])
+ nIdx += ((nWC[i] == 0xff) ? 2 : 1);
+ }
+ if (eColA[nIdx] != COL_BLACK)
+ return Color(eColA[nIdx]); // Standard-Color
+ }
+#endif
+
+ if (nWC[3] & 0x1)
+ {
+ //Special colour gray
+ sal_uInt8 u = (sal_uInt8)( (sal_uLong)( 200 - nWC[0] ) * 256 / 200 );
+ return Color(u, u, u);
+ }
+
+ // User-Color
+ return Color(nWC[0], nWC[1], nWC[2]);
+}
+
+void wwFrameNamer::SetUniqueGraphName(SwFrmFmt *pFrmFmt, const String &rFixed)
+{
+ if (mbIsDisabled || !rFixed.Len())
+ return;
+ String aName(msSeed);
+ aName += String::CreateFromInt32(++mnImportedGraphicsCount);
+ aName.APPEND_CONST_ASC( ": " );
+ aName += rFixed;
+ pFrmFmt->SetName( aName );
+}
+
+// ReadGrafStart liest die ObjektDaten ein und erzeugt falls noetig einen Anker
+bool SwWW8ImplReader::ReadGrafStart(void* pData, short nDataSiz,
+ WW8_DPHEAD* pHd, const WW8_DO* pDo, SfxAllItemSet &rSet)
+{
+ if (SVBT16ToShort(pHd->cb) < sizeof(WW8_DPHEAD) + nDataSiz)
+ {
+ ASSERT( !this, "+Grafik-Element: Size ?" );
+ pStrm->SeekRel(SVBT16ToShort(pHd->cb) - sizeof(WW8_DPHEAD));
+ return false;
+ }
+ pStrm->Read(pData, nDataSiz);
+
+ RndStdIds eAnchor = (SVBT8ToByte(pDo->by) < 2) ? FLY_AT_PAGE : FLY_AT_PARA;
+ rSet.Put(SwFmtAnchor(eAnchor));
+
+ nDrawXOfs2 = nDrawXOfs;
+ nDrawYOfs2 = nDrawYOfs;
+
+ if (eAnchor == FLY_AT_PARA)
+ {
+ if( SVBT8ToByte( pDo->bx ) == 1 ) // Pos: echt links
+ nDrawXOfs2 = static_cast< short >(nDrawXOfs2 - maSectionManager.GetPageLeft());
+ if( nInTable ) // Obj in Table
+ nDrawXOfs2 = nDrawXOfs2 - GetTableLeft(); // -> siehe Kommentar
+ // bei GetTableLeft()
+ }
+ else
+ {
+ if( SVBT8ToByte( pDo->bx ) != 1 )
+ nDrawXOfs2 = static_cast< short >(nDrawXOfs2 + maSectionManager.GetPageLeft());
+ }
+
+ return true;
+}
+
+// SetStdAttr() setzt die Attribute, die jedes Objekt hat
+
+static void SetStdAttr( SfxItemSet& rSet, WW8_DP_LINETYPE& rL,
+ WW8_DP_SHADOW& rSh )
+{
+ if( SVBT16ToShort( rL.lnps ) == 5 ){ // unsichtbar
+ rSet.Put( XLineStyleItem( XLINE_NONE ) );
+ }else{ // sichtbar
+ Color aCol( WW8TransCol( rL.lnpc ) ); // LinienFarbe
+ rSet.Put( XLineColorItem( aEmptyStr, aCol ) );
+ rSet.Put( XLineWidthItem( SVBT16ToShort( rL.lnpw ) ) );
+ // LinienDicke
+ if( SVBT16ToShort( rL.lnps ) >= 1
+ && SVBT16ToShort(rL.lnps ) <= 4 ){ // LinienStil
+ rSet.Put( XLineStyleItem( XLINE_DASH ) );
+ sal_Int16 nLen = SVBT16ToShort( rL.lnpw );
+ XDash aD( XDASH_RECT, 1, 2 * nLen, 1, 5 * nLen, 5 * nLen );
+ switch( SVBT16ToShort( rL.lnps ) ){
+ case 1: aD.SetDots( 0 ); // Dash
+ aD.SetDashLen( 6 * nLen );
+ aD.SetDistance( 4 * nLen );
+ break;
+ case 2: aD.SetDashes( 0 ); break; // Dot
+ case 3: break; // Dash Dot
+ case 4: aD.SetDots( 2 ); break; // Dash Dot Dot
+ }
+ rSet.Put( XLineDashItem( aEmptyStr, aD ) );
+ }else{
+ rSet.Put( XLineStyleItem( XLINE_SOLID ) ); // noetig fuer TextBox
+ }
+ }
+ if( SVBT16ToShort( rSh.shdwpi ) ){ // Schatten
+ rSet.Put(SdrShadowItem(true));
+ rSet.Put( SdrShadowXDistItem( SVBT16ToShort( rSh.xaOffset ) ) );
+ rSet.Put( SdrShadowYDistItem( SVBT16ToShort( rSh.yaOffset ) ) );
+ }
+}
+
+// SetFill setzt Fuellattribute wie Vordergrund- und Hintergrund-Farbe
+// und Muster durch Reduktion auf eine Farbe.
+// SetFill() setzt z.Zt kein Muster, da Sdr das nur sehr umstaendlich kann
+// und die Sdr-Schraffur ( XDash ) noch nicht fertig ist.
+// Statt dessen wird eine Mischfarbe gewaehlt, die auf den entsprechenden
+// Farbton zwischen den Farben liegt.
+
+static void SetFill( SfxItemSet& rSet, WW8_DP_FILL& rFill )
+{
+ static sal_uInt8 nPatA[] =
+ {
+ 0, 0, 5, 10, 20, 25, 30, 40, 50, 60, 70, 75, 80,
+ 90, 50, 50, 50, 50, 50, 50, 33, 33, 33, 33, 33, 33
+ };
+ sal_uInt16 nPat = SVBT16ToShort(rFill.flpp);
+
+ if (nPat == 0) // transparent
+ rSet.Put(XFillStyleItem(XFILL_NONE));
+ else
+ {
+ rSet.Put(XFillStyleItem(XFILL_SOLID)); // necessary for textbox
+ if (nPat <= 1 || nPat > sizeof(nPatA))
+ {
+ // Solid Background or unknown
+ rSet.Put(XFillColorItem(aEmptyStr, WW8TransCol(rFill.dlpcBg)));
+ }
+ else
+ { // Brush -> Farbmischung
+ Color aB( WW8TransCol( rFill.dlpcBg ) );
+ Color aF( WW8TransCol( rFill.dlpcFg ) );
+ aB.SetRed( (sal_uInt8)( ( (sal_uLong)aF.GetRed() * nPatA[nPat]
+ + (sal_uLong)aB.GetRed() * ( 100 - nPatA[nPat] ) ) / 100 ) );
+ aB.SetGreen( (sal_uInt8)( ( (sal_uLong)aF.GetGreen() * nPatA[nPat]
+ + (sal_uLong)aB.GetGreen() * ( 100 - nPatA[nPat] ) ) / 100 ) );
+ aB.SetBlue( (sal_uInt8)( ( (sal_uLong)aF.GetBlue() * nPatA[nPat]
+ + (sal_uLong)aB.GetBlue() * ( 100 - nPatA[nPat] ) ) / 100 ) );
+ rSet.Put( XFillColorItem( aEmptyStr, aB ) );
+ }
+ }
+}
+
+static void SetLineEndAttr( SfxItemSet& rSet, WW8_DP_LINEEND& rLe,
+ WW8_DP_LINETYPE& rLt )
+{
+ sal_uInt16 aSB = SVBT16ToShort( rLe.aStartBits );
+ if( aSB & 0x3 )
+ {
+ ::basegfx::B2DPolygon aPolygon;
+ aPolygon.append(::basegfx::B2DPoint(0.0, 330.0));
+ aPolygon.append(::basegfx::B2DPoint(100.0, 0.0));
+ aPolygon.append(::basegfx::B2DPoint(200.0, 330.0));
+ aPolygon.setClosed(true);
+ rSet.Put( XLineEndItem( aEmptyStr, ::basegfx::B2DPolyPolygon(aPolygon) ) );
+ sal_uInt16 nSiz = SVBT16ToShort( rLt.lnpw )
+ * ( ( aSB >> 2 & 0x3 ) + ( aSB >> 4 & 0x3 ) );
+ if( nSiz < 220 ) nSiz = 220;
+ rSet.Put(XLineEndWidthItem(nSiz));
+ rSet.Put(XLineEndCenterItem(false));
+ }
+
+ sal_uInt16 aEB = SVBT16ToShort( rLe.aEndBits );
+ if( aEB & 0x3 ){
+ ::basegfx::B2DPolygon aPolygon;
+ aPolygon.append(::basegfx::B2DPoint(0.0, 330.0));
+ aPolygon.append(::basegfx::B2DPoint(100.0, 0.0));
+ aPolygon.append(::basegfx::B2DPoint(200.0, 330.0));
+ aPolygon.setClosed(true);
+ rSet.Put( XLineStartItem( aEmptyStr, ::basegfx::B2DPolyPolygon(aPolygon) ) );
+ sal_uInt16 nSiz = SVBT16ToShort( rLt.lnpw )
+ * ( ( aEB >> 2 & 0x3 ) + ( aEB >> 4 & 0x3 ) );
+ if( nSiz < 220 ) nSiz = 220;
+ rSet.Put(XLineStartWidthItem(nSiz));
+ rSet.Put(XLineStartCenterItem(false));
+ }
+}
+
+// Ab hier folgen die Routinen fuer die einzelnen Objekte
+SdrObject* SwWW8ImplReader::ReadLine( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ WW8_DP_LINE aLine;
+
+ if( !ReadGrafStart( (void*)&aLine, sizeof( aLine ), pHd, pDo, rSet ) )
+ return 0;
+
+ Point aP[2];
+ {
+ Point& rP0 = aP[0];
+ Point& rP1 = aP[1];
+
+ rP0.X() = (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2;
+ rP0.Y() = (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2;
+ rP1 = rP0;
+ rP0.X() += (sal_Int16)SVBT16ToShort( aLine.xaStart );
+ rP0.Y() += (sal_Int16)SVBT16ToShort( aLine.yaStart );
+ rP1.X() += (sal_Int16)SVBT16ToShort( aLine.xaEnd );
+ rP1.Y() += (sal_Int16)SVBT16ToShort( aLine.yaEnd );
+ }
+
+ ::basegfx::B2DPolygon aPolygon;
+ aPolygon.append(::basegfx::B2DPoint(aP[0].X(), aP[0].Y()));
+ aPolygon.append(::basegfx::B2DPoint(aP[1].X(), aP[1].Y()));
+ SdrObject* pObj = new SdrPathObj(OBJ_LINE, ::basegfx::B2DPolyPolygon(aPolygon));
+
+ SetStdAttr( rSet, aLine.aLnt, aLine.aShd );
+ SetLineEndAttr( rSet, aLine.aEpp, aLine.aLnt );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadRect( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ WW8_DP_RECT aRect;
+
+ if( !ReadGrafStart( (void*)&aRect, sizeof( aRect ), pHd, pDo, rSet ) )
+ return 0;
+
+ Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
+ (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
+ Point aP1( aP0 );
+ aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
+ aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
+
+ SdrObject* pObj = new SdrRectObj( Rectangle( aP0, aP1 ) );
+
+ SetStdAttr( rSet, aRect.aLnt, aRect.aShd );
+ SetFill( rSet, aRect.aFill );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadElipse( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ WW8_DP_ELIPSE aElipse;
+
+ if( !ReadGrafStart( (void*)&aElipse, sizeof( aElipse ), pHd, pDo, rSet ) )
+ return 0;
+
+ Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
+ (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
+ Point aP1( aP0 );
+ aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
+ aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
+
+ SdrObject* pObj = new SdrCircObj( OBJ_CIRC, Rectangle( aP0, aP1 ) );
+
+ SetStdAttr( rSet, aElipse.aLnt, aElipse.aShd );
+ SetFill( rSet, aElipse.aFill );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadArc( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ WW8_DP_ARC aArc;
+
+ if( !ReadGrafStart( (void*)&aArc, sizeof( aArc ), pHd, pDo, rSet ) )
+ return 0;
+
+ Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
+ (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
+ Point aP1( aP0 );
+ aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa ) * 2;
+ aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya ) * 2;
+
+ short nA[] = { 2, 3, 1, 0 };
+ short nW = nA[ ( ( SVBT8ToByte( aArc.fLeft ) & 1 ) << 1 )
+ + ( SVBT8ToByte( aArc.fUp ) & 1 ) ];
+ if( !SVBT8ToByte( aArc.fLeft ) ){
+ aP0.Y() -= (sal_Int16)SVBT16ToShort( pHd->dya );
+ aP1.Y() -= (sal_Int16)SVBT16ToShort( pHd->dya );
+ }
+ if( SVBT8ToByte( aArc.fUp ) ){
+ aP0.X() -= (sal_Int16)SVBT16ToShort( pHd->dxa );
+ aP1.X() -= (sal_Int16)SVBT16ToShort( pHd->dxa );
+ }
+
+ SdrObject* pObj = new SdrCircObj( OBJ_SECT, Rectangle( aP0, aP1 ),
+ nW * 9000, ( ( nW + 1 ) & 3 ) * 9000 );
+
+ SetStdAttr( rSet, aArc.aLnt, aArc.aShd );
+ SetFill( rSet, aArc.aFill );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadPolyLine( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ WW8_DP_POLYLINE aPoly;
+
+ if( !ReadGrafStart( (void*)&aPoly, sizeof( aPoly ), pHd, pDo, rSet ) )
+ return 0;
+
+ sal_uInt16 nCount = SVBT16ToShort( aPoly.aBits1 ) >> 1 & 0x7fff;
+ SVBT16 *pP = new SVBT16[nCount * 2];
+ pStrm->Read( pP, nCount * 4 ); // Punkte einlesen
+ Polygon aP( nCount );
+ Point aPt;
+ sal_uInt16 i;
+
+ for( i=0; i<nCount; i++ ){
+ aPt.X() = SVBT16ToShort( pP[i << 1] ) + nDrawXOfs2
+ + (sal_Int16)SVBT16ToShort( pHd->xa );
+ aPt.Y() = SVBT16ToShort( pP[( i << 1 ) + 1] ) + nDrawYOfs2
+ + (sal_Int16)SVBT16ToShort( pHd->ya );
+ aP[i] = aPt;
+ }
+ delete[] pP;
+
+ SdrObject* pObj = new SdrPathObj(( SVBT16ToShort( aPoly.aBits1 ) & 0x1 ) ? OBJ_POLY : OBJ_PLIN, ::basegfx::B2DPolyPolygon(aP.getB2DPolygon()));
+ SetStdAttr( rSet, aPoly.aLnt, aPoly.aShd );
+ SetFill( rSet, aPoly.aFill );
+
+ return pObj;
+}
+
+ESelection SwWW8ImplReader::GetESelection( long nCpStart, long nCpEnd )
+{
+ sal_uInt16 nPCnt = mpDrawEditEngine->GetParagraphCount();
+ sal_uInt16 nSP = 0;
+ sal_uInt16 nEP = 0;
+ while( (nSP < nPCnt)
+ && (nCpStart >= mpDrawEditEngine->GetTextLen( nSP ) + 1) )
+ {
+ nCpStart -= mpDrawEditEngine->GetTextLen( nSP ) + 1;
+ nSP++;
+ }
+ // Beim Ende erst 1 Zeichen spaeter auf naechste Zeile umschalten,
+ // da sonst Zeilenattribute immer eine Zeile zu weit reichen.
+ while( (nEP < nPCnt)
+ && (nCpEnd > mpDrawEditEngine->GetTextLen( nEP ) + 1) )
+ {
+ nCpEnd -= mpDrawEditEngine->GetTextLen( nEP ) + 1;
+ nEP++;
+ }
+ return ESelection( nSP, (sal_uInt16)nCpStart, nEP, (sal_uInt16)nCpEnd );
+}
+
+// InsertTxbxStyAttrs() setzt die Style-Attribute in den uebergebenen ItemSet.
+// Es werden die SW-Styles genommen, die Import-WW-Styles sind zu diesem
+// Zeitpunkt schon destruiert.
+// Die SW-Styles werden per Tiefensuche, d.h. mit Parent-Styles nach den
+// in aSrcTab angegebenen Attributen untersucht. Diese werden per Clone
+// dupliziert, bei den Duplikaten werden die Which-IDs
+// gemaess der Tabelle aDstTab umgesetzt, damit die EditEngine sie nicht
+// ignoriert.
+// Es werden hierbei sowohl Para- wie auch Zeichen-Attribute in den
+// ItemSet gestopft.
+void SwWW8ImplReader::InsertTxbxStyAttrs( SfxItemSet& rS, sal_uInt16 nColl )
+{
+ SwWW8StyInf * pStyInf = GetStyle(nColl);
+ if( pStyInf != NULL && pStyInf->pFmt && pStyInf->bColl )
+ {
+ const SfxPoolItem* pItem;
+ for( sal_uInt16 i = POOLATTR_BEGIN; i < POOLATTR_END; i++ )
+ {
+ //If we are set in the source and not set in the destination
+ //then add it in.
+ if ( SFX_ITEM_SET == pStyInf->pFmt->GetItemState(
+ i, true, &pItem ) )
+ {
+ SfxItemPool *pEditPool = rS.GetPool();
+ sal_uInt16 nWhich = i;
+ sal_uInt16 nSlotId = rDoc.GetAttrPool().GetSlotId(nWhich);
+ if (
+ nSlotId && nWhich != nSlotId &&
+ 0 != (nWhich = pEditPool->GetWhich(nSlotId)) &&
+ nWhich != nSlotId &&
+ ( SFX_ITEM_SET != rS.GetItemState(nWhich, false) )
+ )
+ {
+ SfxPoolItem* pCopy = pItem->Clone();
+ pCopy->SetWhich( nWhich );
+ rS.Put( *pCopy );
+ delete pCopy;
+ }
+ }
+ }
+ }
+
+}
+
+static void lcl_StripFields(String &rString, long &rNewStartCp)
+{
+ for(sal_uInt16 i=0; i < rString.Len(); i++)
+ {
+ if( 0x13 == rString.GetChar( i ) )
+ {
+ do
+ {
+ rString.Erase( i, 1 );
+ rNewStartCp++;
+ }
+ while( rString.Len()
+ && ( i < rString.Len())
+ && (0x14 != rString.GetChar( i ) )
+ && (0x15 != rString.GetChar( i ) ) );
+ if( rString.Len() )
+ {
+ if( 0x14 == rString.GetChar( i ) )
+ {
+ rString.Erase( i, 1 );
+ rNewStartCp++;
+ do
+ {
+ i++;
+ }
+ while( rString.Len()
+ && ( i < rString.Len())
+ && (0x15 != rString.GetChar( i ) ) );
+ if( i < rString.Len() )
+ rString.Erase( i, 1 );
+ }
+ else if( 0x15 == rString.GetChar( i ) )
+ rString.Erase( i, 1 );
+ }
+ }
+ }
+}
+
+class Chunk
+{
+private:
+ String msURL;
+ long mnStartPos; //0x13
+ long mnEndPos; //0x15
+public:
+ explicit Chunk(long nStart, const String &rURL)
+ : msURL(rURL), mnStartPos(nStart) {}
+ Chunk(const Chunk &rChunk)
+ : msURL(rChunk.msURL), mnStartPos(rChunk.mnStartPos),
+ mnEndPos(rChunk.mnEndPos) {}
+ Chunk& operator=(const Chunk &rChunk)
+ {
+ msURL = rChunk.msURL;
+ mnStartPos = rChunk.mnStartPos;
+ mnEndPos = rChunk.mnEndPos;
+ return *this;
+ }
+ void SetEndPos(long nEnd) { mnEndPos = nEnd; }
+ long GetStartPos() const {return mnStartPos;}
+ long GetEndPos() const {return mnEndPos;}
+ const String &GetURL() const {return msURL;}
+ void Adjust(xub_StrLen nAdjust)
+ {
+ mnStartPos-=nAdjust;
+ mnEndPos-=nAdjust;
+ }
+};
+
+// InsertAttrsAsDrawingAttrs() setzt zwischen StartCp und EndCp die Attribute.
+// Dabei werden Style-Attribute als harte Attribute, Absatz- und Zeichen-
+// attribute gesetzt.
+void SwWW8ImplReader::InsertAttrsAsDrawingAttrs(long nStartCp, long nEndCp,
+ ManTypes eType, bool bONLYnPicLocFc)
+{
+ /*
+ Save and create new plcxman for this drawing object, of the type that
+ will include the para end mark inside a paragraph property range, as
+ drawing boxes have real paragraph marks as part of their text, while
+ normal writer has seperate nodes for each paragraph and so has no actual
+ paragraph mark as part of the paragraph text.
+ */
+ WW8ReaderSave aSave(this);
+ pPlcxMan = new WW8PLCFMan(pSBase, eType, nStartCp, true);
+
+ WW8_CP nStart = pPlcxMan->Where();
+ WW8_CP nNext, nEnd, nStartReplace=0;
+
+ bool bDoingSymbol = false;
+ sal_Unicode cReplaceSymbol = cSymbol;
+
+ SfxItemSet *pS = new SfxItemSet(mpDrawEditEngine->GetEmptyItemSet());
+ WW8PLCFManResult aRes;
+
+ std::deque<Chunk> aChunks;
+
+ //Here store stack location
+ sal_uInt16 nCurrentCount = static_cast< sal_uInt16 >(pCtrlStck->Count());
+ while (nStart < nEndCp)
+ {
+ //nStart is the beginning of the attributes for this range, and
+ //may be before the text itself. So watch out for that
+ WW8_CP nTxtStart = nStart;
+ if (nTxtStart < nStartCp)
+ nTxtStart = nStartCp;
+ // get position of next SPRM
+ bool bStartAttr = pPlcxMan->Get(&aRes);
+ nAktColl = pPlcxMan->GetColl();
+ if (aRes.nSprmId)
+ {
+ if( bONLYnPicLocFc )
+ {
+ if ( (68 == aRes.nSprmId) || (0x6A03 == aRes.nSprmId) )
+ {
+ Read_PicLoc(aRes.nSprmId, aRes.pMemPos +
+ mpSprmParser->DistanceToData(aRes.nSprmId), 4);
+ // Ok, that's what we were looking for. Now let's get
+ // out of here!
+ break;
+ }
+ }
+ else if ( aRes.nSprmId && (
+ (eFTN > aRes.nSprmId) || (0x0800 <= aRes.nSprmId) ) )
+ {
+ //Here place them onto our usual stack and we will pop them
+ //off and convert them later
+ if (bStartAttr)
+ {
+ ImportSprm(aRes.pMemPos, aRes.nSprmId);
+ if (!bDoingSymbol && bSymbol == true)
+ {
+ bDoingSymbol = true;
+ nStartReplace = nTxtStart;
+ cReplaceSymbol = cSymbol;
+ }
+ }
+ else
+ {
+ EndSprm( aRes.nSprmId );
+ if (bSymbol == false && bDoingSymbol)
+ {
+ bDoingSymbol = false;
+ String sTemp;
+ sTemp.Fill(writer_cast<xub_StrLen>(
+ nTxtStart - nStartReplace), cReplaceSymbol);
+ mpDrawEditEngine->QuickInsertText(sTemp,
+ GetESelection(nStartReplace - nStartCp,
+ nTxtStart - nStartCp ) );
+ }
+ }
+ }
+ else if (aRes.nSprmId == eFLD)
+ {
+ if (bStartAttr)
+ {
+ sal_uInt16 nCount = static_cast< sal_uInt16 >(pCtrlStck->Count());
+ if (maFieldStack.empty() && Read_Field(&aRes))
+ {
+ String sURL;
+ for (sal_uInt16 nI = static_cast< sal_uInt16 >(pCtrlStck->Count()); nI > nCount; --nI)
+ {
+ const SfxPoolItem *pItem = ((*pCtrlStck)[nI-1])->pAttr;
+ sal_uInt16 nWhich = pItem->Which();
+ if (nWhich == RES_TXTATR_INETFMT)
+ {
+ const SwFmtINetFmt *pURL =
+ (const SwFmtINetFmt *)pItem;
+ sURL = pURL->GetValue();
+ }
+ pCtrlStck->DeleteAndDestroy(nI-1);
+ }
+ aChunks.push_back(Chunk(nStart, sURL));
+ }
+ }
+ else
+ {
+ if (!maFieldStack.empty() && End_Field())
+ aChunks.back().SetEndPos(nStart+1);
+ }
+ }
+ }
+
+ (*pPlcxMan)++;
+ nNext = pPlcxMan->Where();
+
+ if( (nNext != nStart) && !bONLYnPicLocFc )
+ {
+ nEnd = ( nNext < nEndCp ) ? nNext : nEndCp;
+ SfxItemPool *pEditPool = pS->GetPool();
+
+ //Here read current properties and convert them into pS
+ //and put those attrs into the draw box if they can be converted
+ //to draw attributes
+ if (pCtrlStck->Count() - nCurrentCount)
+ {
+ for (sal_uInt16 i = nCurrentCount; i < pCtrlStck->Count(); i++)
+ {
+ const SfxPoolItem *pItem = ((*pCtrlStck)[i])->pAttr;
+ sal_uInt16 nWhich = pItem->Which();
+ if( nWhich < RES_FLTRATTR_BEGIN ||
+ nWhich >= RES_FLTRATTR_END )
+ {
+ sal_uInt16 nSlotId = rDoc.GetAttrPool().GetSlotId(nWhich);
+ if (
+ nSlotId && nWhich != nSlotId &&
+ 0 != (nWhich = pEditPool->GetWhich(nSlotId)) &&
+ nWhich != nSlotId
+ )
+ {
+ SfxPoolItem* pCopy = pItem->Clone();
+ pCopy->SetWhich( nWhich );
+ pS->Put( *pCopy );
+ delete pCopy;
+ }
+ }
+ }
+ }
+ //Fill in the remainder from the style
+ InsertTxbxStyAttrs(*pS, nAktColl);
+
+ if( pS->Count() )
+ {
+ mpDrawEditEngine->QuickSetAttribs( *pS,
+ GetESelection( nTxtStart - nStartCp, nEnd - nStartCp ) );
+ delete pS;
+ pS = new SfxItemSet(mpDrawEditEngine->GetEmptyItemSet());
+ }
+ }
+ nStart = nNext;
+ }
+ delete pS;
+
+ //pop off as far as recorded location just in case there were some left
+ //unclosed
+ for (sal_uInt16 nI = static_cast< sal_uInt16 >(pCtrlStck->Count()); nI > nCurrentCount; --nI)
+ pCtrlStck->DeleteAndDestroy(nI-1);
+
+ typedef std::deque<Chunk>::iterator myIter;
+ myIter aEnd = aChunks.end();
+ for (myIter aIter = aChunks.begin(); aIter != aEnd; ++aIter)
+ {
+ ESelection aSel(GetESelection(aIter->GetStartPos()-nStartCp,
+ aIter->GetEndPos()-nStartCp));
+ String aString(mpDrawEditEngine->GetText(aSel));
+ xub_StrLen nOrigLen = aString.Len();
+ long nDummy(0);
+ lcl_StripFields(aString, nDummy);
+
+ xub_StrLen nChanged;
+ if (aIter->GetURL().Len())
+ {
+ SvxURLField aURL(aIter->GetURL(), aString,
+ SVXURLFORMAT_APPDEFAULT);
+ mpDrawEditEngine->QuickInsertField(SvxFieldItem(aURL, EE_FEATURE_FIELD), aSel);
+ nChanged = nOrigLen - 1;
+ }
+ else
+ {
+ mpDrawEditEngine->QuickInsertText(aString, aSel);
+ nChanged = nOrigLen - aString.Len();
+ }
+ for (myIter aIter2 = aIter+1; aIter2 != aEnd; ++aIter2)
+ aIter2->Adjust(nChanged);
+ }
+
+ /*
+ Don't worry about the new pPlcxMan, the restorer removes it when
+ replacing the current one with the old one.
+ */
+ aSave.Restore(this);
+}
+
+bool SwWW8ImplReader::GetTxbxTextSttEndCp(WW8_CP& rStartCp, WW8_CP& rEndCp,
+ sal_uInt16 nTxBxS, sal_uInt16 nSequence)
+{
+ // rasch den TextBox-PLCF greifen
+ WW8PLCFspecial* pT = pPlcxMan ? pPlcxMan->GetTxbx() : 0;
+ if( !pT )
+ {
+ ASSERT( !this, "+Wo ist der Grafik-Text (1) ?" );
+ return false;
+ }
+
+ // ggfs. zuerst die richtige TextBox-Story finden
+ bool bCheckTextBoxStory = ( nTxBxS && pT->GetIMax() >= nTxBxS );
+ if( bCheckTextBoxStory )
+ pT->SetIdx( nTxBxS-1 );
+
+ // dann Start und Ende ermitteln
+ void* pT0;
+ if( !pT->Get( rStartCp, pT0 ) )
+ {
+ ASSERT( !this, "+Wo ist der Grafik-Text (2) ?" );
+ return false;
+ }
+
+ if( bCheckTextBoxStory )
+ {
+ bool bReusable = (0 != SVBT16ToShort( ((WW8_TXBXS*)pT0)->fReusable ));
+ while( bReusable )
+ {
+ (*pT)++;
+ if( !pT->Get( rStartCp, pT0 ) )
+ {
+ ASSERT( !this, "+Wo ist der Grafik-Text (2-a) ?" );
+ return false;
+ }
+ bReusable = (0 != SVBT16ToShort( ((WW8_TXBXS*)pT0)->fReusable ));
+ }
+ }
+ (*pT)++;
+ if( !pT->Get( rEndCp, pT0 ) )
+ {
+ ASSERT( !this, "+Wo ist der Grafik-Text (3) ?" );
+ return false;
+ }
+
+ // jetzt ggfs. die passende Page in der Break-Table finden
+ if( bCheckTextBoxStory )
+ {
+ // Sonderfall: gesamte(!) Kette soll ermittelt werden,
+ // dann sind wir hier schon fertig!
+ if( USHRT_MAX > nSequence )
+ {
+ long nMinStartCp = rStartCp;
+ long nMaxEndCp = rEndCp;
+ // rasch den TextBox-Break-Deskriptor-PLCF greifen
+ pT = pPlcxMan->GetTxbxBkd();
+ if (!pT) //It can occur on occasion, Caolan
+ return false;
+
+ // den ersten Eintrag fuer diese TextBox-Story finden
+ if( !pT->SeekPos( rStartCp ) )
+ {
+ ASSERT( !this, "+Wo ist der Grafik-Text (4) ?" );
+ return false;
+ }
+ // ggfs. entsprechende Anzahl Eintraege weitergehen
+ for(sal_uInt16 iSequence = 0; iSequence < nSequence; iSequence++) (*pT)++;
+ // dann die tatsaechlichen Start und Ende ermitteln
+ if( (!pT->Get( rStartCp, pT0 ))
+ || ( nMinStartCp > rStartCp ) )
+ {
+ ASSERT( !this, "+Wo ist der Grafik-Text (5) ?" );
+ return false;
+ }
+ if( rStartCp >= nMaxEndCp )
+ rEndCp = rStartCp; // kein Error: leerer String!
+ else
+ {
+ (*pT)++;
+ if( (!pT->Get( rEndCp, pT0 ))
+ || ( nMaxEndCp < rEndCp-1 ) )
+ {
+ ASSERT( !this, "+Wo ist der Grafik-Text (6) ?" );
+ return false;
+ }
+ rEndCp -= 1;
+ }
+ }
+ else
+ rEndCp -= 1;
+ }
+ else
+ rEndCp -= 1;
+ return true;
+}
+
+// TxbxText() holt aus WW-File den Text und gibt diesen und den Anfangs- und
+// den um -2 (bzw. -1 bei Ver8) korrigierten End-Cp zurueck
+bool SwWW8ImplReader::GetRangeAsDrawingString(String& rString, long nStartCp, long nEndCp, ManTypes eType)
+{
+ WW8_CP nOffset = pWwFib->GetBaseCp(eType);
+
+ bool bOk = false;
+ ASSERT(nStartCp <= nEndCp, "+Wo ist der Grafik-Text (7) ?");
+ if (nStartCp == nEndCp)
+ rString.Erase(); // leerer String: durchaus denkbar!
+ else if (nStartCp < nEndCp)
+ {
+ // den Text einlesen: kann sich ueber mehrere Pieces erstrecken!!!
+ sal_uInt16 nLen = pSBase->WW8ReadString(*pStrm, rString,
+ nStartCp + nOffset, nEndCp - nStartCp, GetCurrentCharSet());
+ ASSERT(nLen, "+Wo ist der Grafik-Text (8) ?");
+ if (nLen)
+ {
+ bOk = true;
+ if( 0x0d == rString.GetChar(nLen - 1) )
+ rString.Erase(nLen - 1);
+
+ rString.SearchAndReplaceAll( 0xb, 0xa );
+ }
+ }
+ return bOk;
+}
+
+OutlinerParaObject* SwWW8ImplReader::ImportAsOutliner(String &rString, WW8_CP nStartCp, WW8_CP nEndCp, ManTypes eType)
+{
+ OutlinerParaObject* pRet = 0;
+
+ if (GetRangeAsDrawingString( rString, nStartCp, nEndCp, eType ))
+ {
+ if (!mpDrawEditEngine)
+ mpDrawEditEngine = new EditEngine(0);
+
+ mpDrawEditEngine->SetText(rString);
+ InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType);
+
+ //Annotations typically begin with a (useless) 0x5
+ if ((eType == MAN_AND) && mpDrawEditEngine->GetTextLen())
+ {
+ ESelection aFirstChar(0, 0, 0, 1);
+ if (mpDrawEditEngine->GetText( aFirstChar ) == String(sal_Unicode(0x5)))
+ mpDrawEditEngine->QuickDelete(aFirstChar);
+ }
+
+ EditTextObject* pTemporaryText = mpDrawEditEngine->CreateTextObject();
+ pRet = new OutlinerParaObject(*pTemporaryText);
+ pRet->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT );
+ delete pTemporaryText;
+
+ mpDrawEditEngine->SetText( aEmptyStr );
+ mpDrawEditEngine->SetParaAttribs(0, mpDrawEditEngine->GetEmptyItemSet());
+
+ //Strip out fields, leaving the result
+ long nDummy(0);
+ lcl_StripFields(rString, nDummy);
+ //Strip out word's special characters for the simple string
+ rString.EraseAllChars(0x1);
+ rString.EraseAllChars(0x5);
+ rString.EraseAllChars(0x8);
+ rString.SearchAndReplaceAllAscii("\007\007", String::CreateFromAscii("\007\012"));
+ rString.SearchAndReplaceAll(0x7, ' ');
+
+ }
+
+ return pRet;
+}
+
+// InsertTxbxText() fuegt fuer TextBoxen und CaptionBoxen den Text
+// und die Attribute ein
+SwFrmFmt* SwWW8ImplReader::InsertTxbxText(SdrTextObj* pTextObj,
+ Size* pObjSiz, sal_uInt16 nTxBxS, sal_uInt16 nSequence, long nPosCp,
+ SwFrmFmt* pOldFlyFmt, bool bMakeSdrGrafObj, bool& rbEraseTextObj,
+ bool* pbTestTxbxContainsText, long* pnStartCp, long* pnEndCp,
+ bool* pbContainsGraphics, SvxMSDffImportRec* pRecord)
+{
+ SwFrmFmt* pFlyFmt = 0;
+ sal_uLong nOld = pStrm->Tell();
+
+ ManTypes eType = pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX;
+
+ rbEraseTextObj = false;
+
+ String aString;
+ WW8_CP nStartCp, nEndCp;
+ bool bContainsGraphics = false;
+ bool bTextWasRead = GetTxbxTextSttEndCp( nStartCp, nEndCp, nTxBxS,
+ nSequence ) && GetRangeAsDrawingString( aString, nStartCp, nEndCp, eType );
+
+ if (!mpDrawEditEngine)
+ mpDrawEditEngine = new EditEngine(0);
+ if( pObjSiz )
+ mpDrawEditEngine->SetPaperSize( *pObjSiz );
+
+ String aOrigString(aString);
+ if( bTextWasRead )
+ {
+ long nNewStartCp = nStartCp;
+ lcl_StripFields(aString, nNewStartCp);
+
+ if (1 != aString.Len())
+ {
+ if ( (STRING_NOTFOUND != aString.Search(0x1)) ||
+ (STRING_NOTFOUND != aString.Search(0x8)) )
+ {
+ bContainsGraphics = true;
+ }
+ }
+ else // May be a single graphic or object
+ {
+ bool bDone = true;
+ switch( aString.GetChar(0) )
+ {
+ case 0x1:
+ if (!pbTestTxbxContainsText)
+ {
+ WW8ReaderSave aSave(this, nNewStartCp -1);
+ bool bOldEmbeddObj = bEmbeddObj;
+ //bEmbedd Ordinarily would have been set by field
+ //parse, but this is impossible here so...
+ bEmbeddObj = true;
+
+ // 1st look for OLE- or Graph-Indicator Sprms
+ WW8PLCFx_Cp_FKP* pChp = pPlcxMan->GetChpPLCF();
+ WW8PLCFxDesc aDesc;
+ pChp->GetSprms( &aDesc );
+ WW8SprmIter aSprmIter(aDesc.pMemPos, aDesc.nSprmsLen,
+ *mpSprmParser);
+
+ const sal_uInt8* pParams = aSprmIter.GetAktParams();
+ for( int nLoop = 0; nLoop < 2; ++nLoop )
+ {
+ while( aSprmIter.GetSprms()
+ && (0 != (pParams = aSprmIter.GetAktParams())) )
+ {
+ sal_uInt16 nAktId = aSprmIter.GetAktId();
+ switch( nAktId )
+ {
+ case 75:
+ case 118:
+ case 0x080A:
+ case 0x0856:
+ Read_Obj(nAktId, pParams, 1);
+ break;
+ case 68: // Read_Pic()
+ case 0x6A03:
+ case 0x680E:
+ Read_PicLoc(nAktId, pParams, 1);
+ break;
+ }
+ aSprmIter++;
+ }
+
+ //if( bRead_Obj || bRead_PicLoc ) break;
+ if( !nLoop )
+ {
+ pChp->GetPCDSprms( aDesc );
+ aSprmIter.SetSprms( aDesc.pMemPos,
+ aDesc.nSprmsLen );
+ }
+ //if( bRead_Obj || bRead_PicLoc ) break;
+ }
+ aSave.Restore(this);
+ bEmbeddObj=bOldEmbeddObj;
+
+ // then import either an OLE of a Graphic
+ if( bObj )
+ {
+ if( bMakeSdrGrafObj && pTextObj &&
+ pTextObj->GetUpGroup() )
+ {
+ // SdrOleObj/SdrGrafObj anstatt des
+ // SdrTextObj in dessen Gruppe einsetzen
+
+ Graphic aGraph;
+ SdrObject* pNew = ImportOleBase(aGraph);
+
+ if( !pNew )
+ {
+ pNew = new SdrGrafObj;
+ ((SdrGrafObj*)pNew)->SetGraphic(aGraph);
+ }
+
+ GrafikCtor();
+
+ pNew->SetModel( pDrawModel );
+ pNew->SetLogicRect( pTextObj->GetCurrentBoundRect() );
+ pNew->SetLayer( pTextObj->GetLayer() );
+
+ pTextObj->GetUpGroup()->GetSubList()->
+ ReplaceObject(pNew, pTextObj->GetOrdNum());
+ }
+ else
+ pFlyFmt = ImportOle();
+ bObj = false;
+ }
+ else
+ {
+ InsertAttrsAsDrawingAttrs(nNewStartCp, nNewStartCp+1,
+ eType, true);
+ pFlyFmt = ImportGraf(bMakeSdrGrafObj ? pTextObj : 0,
+ pOldFlyFmt);
+ }
+ }
+ break;
+ case 0x8:
+ if ( (!pbTestTxbxContainsText) && (!bObj) )
+ pFlyFmt = Read_GrafLayer( nPosCp );
+ break;
+ default:
+ bDone = false;
+ break;
+ }
+
+ if( bDone )
+ {
+ if( pFlyFmt )
+ {
+ if( pRecord )
+ {
+ SfxItemSet aFlySet( rDoc.GetAttrPool(),
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
+
+ Rectangle aInnerDist( pRecord->nDxTextLeft,
+ pRecord->nDyTextTop,
+ pRecord->nDxTextRight,
+ pRecord->nDyTextBottom );
+ MatchSdrItemsIntoFlySet( pTextObj,
+ aFlySet,
+ pRecord->eLineStyle,
+ pRecord->eShapeType,
+ aInnerDist );
+
+ pFlyFmt->SetFmtAttr( aFlySet );
+
+ MapWrapIntoFlyFmt(pRecord, pFlyFmt);
+ }
+ }
+ aString.Erase();
+ rbEraseTextObj = (0 != pFlyFmt);
+ }
+ }
+ }
+
+ if( pnStartCp )
+ *pnStartCp = nStartCp;
+ if( pnEndCp )
+ *pnEndCp = nEndCp;
+
+ if( pbTestTxbxContainsText )
+ *pbTestTxbxContainsText = bTextWasRead && ! rbEraseTextObj;
+ else if( !rbEraseTextObj )
+ {
+ if( bTextWasRead )
+ {
+ mpDrawEditEngine->SetText(aOrigString);
+ InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType);
+ }
+
+ bool bVertical = pTextObj->IsVerticalWriting() ? true : false;
+ EditTextObject* pTemporaryText = mpDrawEditEngine->CreateTextObject();
+ OutlinerParaObject* pOp = new OutlinerParaObject(*pTemporaryText);
+ pOp->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT );
+ pOp->SetVertical( bVertical );
+ delete pTemporaryText;
+ pTextObj->NbcSetOutlinerParaObject( pOp );
+ pTextObj->SetVerticalWriting(bVertical);
+
+ // Fuer die naechste Textbox noch die alten Absatz-Attribute
+ // und Styles entfernen, sonst startet die naechste Box
+ // mit falschen Attributen.
+ // Vorgehen: Text loeschen = auf 1 Absatz reduzieren
+ // und an diesem Absatz die Absatzattribute und Styles loeschen
+ // (Empfehlung JOE)
+ mpDrawEditEngine->SetText( aEmptyStr );
+ mpDrawEditEngine->SetParaAttribs(0, mpDrawEditEngine->GetEmptyItemSet());
+ }
+
+ pStrm->Seek( nOld );
+ if (pbContainsGraphics)
+ *pbContainsGraphics = bContainsGraphics;
+ return pFlyFmt;
+}
+
+
+bool SwWW8ImplReader::TxbxChainContainsRealText(sal_uInt16 nTxBxS, long& rStartCp,
+ long& rEndCp)
+{
+ bool bErase, bContainsText;
+ InsertTxbxText( 0,0,nTxBxS,USHRT_MAX,0,0,0, bErase, &bContainsText,
+ &rStartCp, &rEndCp );
+ return bContainsText;
+}
+
+
+// TextBoxes only for Ver67 !!
+SdrObject* SwWW8ImplReader::ReadTxtBox( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ bool bDummy;
+ WW8_DP_TXTBOX aTxtB;
+
+ if( !ReadGrafStart( (void*)&aTxtB, sizeof( aTxtB ), pHd, pDo, rSet ) )
+ return 0;
+
+ Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
+ (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
+ Point aP1( aP0 );
+ aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
+ aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
+
+ SdrObject* pObj = new SdrRectObj( OBJ_TEXT, Rectangle( aP0, aP1 ) );
+ pObj->SetModel( pDrawModel );
+ pObj->NbcSetSnapRect(Rectangle(aP0, aP1));
+ Size aSize( (sal_Int16)SVBT16ToShort( pHd->dxa ) ,
+ (sal_Int16)SVBT16ToShort( pHd->dya ) );
+
+ long nStartCpFly,nEndCpFly;
+ bool bContainsGraphics;
+ InsertTxbxText(PTR_CAST(SdrTextObj,pObj), &aSize, 0, 0, 0, 0, false,
+ bDummy,0,&nStartCpFly,&nEndCpFly,&bContainsGraphics);
+
+ SetStdAttr( rSet, aTxtB.aLnt, aTxtB.aShd );
+ SetFill( rSet, aTxtB.aFill );
+
+ rSet.Put( SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE ) );
+ rSet.Put( SdrTextAutoGrowWidthItem(false));
+ rSet.Put( SdrTextAutoGrowHeightItem(false));
+ rSet.Put( SdrTextLeftDistItem( MIN_BORDER_DIST*2 ) );
+ rSet.Put( SdrTextRightDistItem( MIN_BORDER_DIST*2 ) );
+ rSet.Put( SdrTextUpperDistItem( MIN_BORDER_DIST ) );
+ rSet.Put( SdrTextLowerDistItem( MIN_BORDER_DIST ) );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadCaptionBox( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ static SdrCaptionType aCaptA[] = { SDRCAPT_TYPE1, SDRCAPT_TYPE2,
+ SDRCAPT_TYPE3, SDRCAPT_TYPE4 };
+
+ WW8_DP_CALLOUT_TXTBOX aCallB;
+
+ if( !ReadGrafStart( (void*)&aCallB, sizeof( aCallB ), pHd, pDo, rSet ) )
+ return 0;
+
+ sal_uInt16 nCount = SVBT16ToShort( aCallB.dpPolyLine.aBits1 ) >> 1 & 0x7fff;
+ SVBT16 *pP = new SVBT16[nCount * 2];
+ pStrm->Read( pP, nCount * 4 ); // Punkte einlesen
+ sal_uInt8 nTyp = (sal_uInt8)nCount - 1;
+ if( nTyp == 1 && SVBT16ToShort( pP[0] ) == SVBT16ToShort( pP[2] ) )
+ nTyp = 0;
+
+ Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) +
+ (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.xa ) + nDrawXOfs2,
+ (sal_Int16)SVBT16ToShort( pHd->ya )
+ + (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.ya ) + nDrawYOfs2 );
+ Point aP1( aP0 );
+ aP1.X() += (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dxa );
+ aP1.Y() += (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dya );
+ Point aP2( (sal_Int16)SVBT16ToShort( pHd->xa )
+ + (sal_Int16)SVBT16ToShort( aCallB.dpheadPolyLine.xa )
+ + nDrawXOfs2 + (sal_Int16)SVBT16ToShort( pP[0] ),
+ (sal_Int16)SVBT16ToShort( pHd->ya )
+ + (sal_Int16)SVBT16ToShort( aCallB.dpheadPolyLine.ya )
+ + nDrawYOfs2 + (sal_Int16)SVBT16ToShort( pP[1] ) );
+ delete[] pP;
+
+ SdrCaptionObj* pObj = new SdrCaptionObj( Rectangle( aP0, aP1 ), aP2 );
+ pObj->SetModel( pDrawModel );
+ pObj->NbcSetSnapRect(Rectangle(aP0, aP1));
+ Size aSize( (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dxa ),
+ (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dya ) );
+ bool bEraseThisObject;
+
+ InsertTxbxText(pObj, &aSize, 0, 0, 0, 0, false, bEraseThisObject );
+
+ if( SVBT16ToShort( aCallB.dptxbx.aLnt.lnps ) != 5 ) // Umrandung sichtbar ?
+ SetStdAttr( rSet, aCallB.dptxbx.aLnt, aCallB.dptxbx.aShd );
+ else // nein -> Nimm Linie
+ SetStdAttr( rSet, aCallB.dpPolyLine.aLnt, aCallB.dptxbx.aShd );
+ SetFill( rSet, aCallB.dptxbx.aFill );
+ rSet.Put( SdrCaptionTypeItem( aCaptA[nTyp] ) );
+
+ return pObj;
+}
+
+
+SdrObject *SwWW8ImplReader::ReadGroup( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ sal_Int16 nGrouped;
+
+ if( !ReadGrafStart( (void*)&nGrouped, sizeof( nGrouped ), pHd, pDo, rSet ) )
+ return 0;
+
+#ifdef OSL_BIGENDIAN
+ nGrouped = (sal_Int16)SWAPSHORT( nGrouped );
+#endif
+
+ nDrawXOfs = nDrawXOfs + (sal_Int16)SVBT16ToShort( pHd->xa );
+ nDrawYOfs = nDrawYOfs + (sal_Int16)SVBT16ToShort( pHd->ya );
+
+ SdrObject* pObj = new SdrObjGroup;
+
+ short nLeft = (sal_Int16)SVBT16ToShort( pHd->cb ) - sizeof( WW8_DPHEAD );
+ for (int i = 0; i < nGrouped; i++)
+ {
+ SfxAllItemSet aSet(pDrawModel->GetItemPool());
+ if (SdrObject *pObject = ReadGrafPrimitive(nLeft, pDo, aSet))
+ {
+ // #116150#
+ // first add and then set ItemSet
+ SdrObjList *pSubGroup = pObj->GetSubList();
+ ASSERT(pSubGroup, "Why no sublist available?");
+ if (pSubGroup)
+ pSubGroup->InsertObject(pObject, 0);
+ pObject->SetMergedItemSetAndBroadcast(aSet);
+ }
+ }
+
+ nDrawXOfs = nDrawXOfs - (sal_Int16)SVBT16ToShort( pHd->xa );
+ nDrawYOfs = nDrawYOfs - (sal_Int16)SVBT16ToShort( pHd->ya );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadGrafPrimitive( short& rLeft, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ //cmc: This whole archaic word 6 graphic import can probably be refactored
+ //into an object hierarachy with a little effort.
+ SdrObject *pRet=0;
+ WW8_DPHEAD aHd; // Lese Draw-Primitive-Header
+ pStrm->Read(&aHd, sizeof(WW8_DPHEAD));
+
+ if( rLeft >= SVBT16ToShort(aHd.cb) ) // Vorsichtsmassmahme
+ {
+ rSet.Put(SwFmtSurround(SURROUND_THROUGHT));
+ switch (SVBT16ToShort(aHd.dpk) & 0xff )
+ {
+ case 0:
+ pRet = ReadGroup( &aHd, pDo, rSet );
+ break;
+ case 1:
+ pRet = ReadLine( &aHd, pDo, rSet );
+ break;
+ case 2:
+ pRet = ReadTxtBox( &aHd, pDo, rSet );
+ break;
+ case 3:
+ pRet = ReadRect( &aHd, pDo, rSet );
+ break;
+ case 4:
+ pRet = ReadElipse( &aHd, pDo, rSet );
+ break;
+ case 5:
+ pRet = ReadArc( &aHd, pDo, rSet );
+ break;
+ case 6:
+ pRet = ReadPolyLine( &aHd, pDo, rSet );
+ break;
+ case 7:
+ pRet = ReadCaptionBox( &aHd, pDo, rSet );
+ break;
+ default: // unbekannt
+ pStrm->SeekRel(SVBT16ToShort(aHd.cb) - sizeof(WW8_DPHEAD));
+ break;
+ }
+ }
+ else
+ {
+ ASSERT( !this, "+Grafik-Overlap" );
+ }
+ rLeft = rLeft - SVBT16ToShort( aHd.cb );
+ return pRet;
+}
+
+void SwWW8ImplReader::ReadGrafLayer1( WW8PLCFspecial* pPF, long nGrafAnchorCp )
+{
+ pPF->SeekPos( nGrafAnchorCp );
+ WW8_FC nStartFc;
+ void* pF0;
+ if( !pPF->Get( nStartFc, pF0 ) )
+ {
+ ASSERT( !this, "+Wo ist die Grafik (2) ?" );
+ return;
+ }
+ WW8_FDOA* pF = (WW8_FDOA*)pF0;
+ if( !SVBT32ToUInt32( pF->fc ) )
+ {
+ ASSERT( !this, "+Wo ist die Grafik (3) ?" );
+ return;
+ }
+ WW8_DO aDo;
+ pStrm->Seek( SVBT32ToUInt32( pF->fc ) ); // Lese Draw-Header
+ pStrm->Read( &aDo, sizeof( WW8_DO ) );
+
+ short nLeft = SVBT16ToShort( aDo.cb ) - sizeof( WW8_DO );
+ while (nLeft > static_cast<short>(sizeof(WW8_DPHEAD)))
+ {
+ SfxAllItemSet aSet( pDrawModel->GetItemPool() );
+ if (SdrObject *pObject = ReadGrafPrimitive( nLeft, &aDo, aSet ))
+ {
+ pWWZOrder->InsertDrawingObject(pObject, SVBT16ToShort(aDo.dhgt));
+ SwFrmFmt *pFrm = rDoc.Insert( *pPaM, *pObject, &aSet, NULL);
+ pObject->SetMergedItemSet(aSet);
+ pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFrm);
+ }
+ }
+}
+
+const WW8_BordersSO &WW8_BordersSO::Get0x01LineMatch(eBorderCode eCode)
+{
+ /*
+ // Linien-Defaults in Twips: fruehere Writer-Defaults,
+ // siehe auch <editeng/boxitem.hxx>
+ #define DEF_LINE_WIDTH_0 1
+ #define DEF_LINE_WIDTH_1 20
+ #define DEF_LINE_WIDTH_2 50
+ #define DEF_LINE_WIDTH_3 80
+ #define DEF_LINE_WIDTH_4 100
+ #define DEF_LINE_WIDTH_5 10
+
+ #define DEF_MAX_LINE_WIDHT DEF_LINE_WIDTH_4
+ #define DEF_MAX_LINE_DIST DEF_LINE_WIDTH_2
+
+ #define DEF_DOUBLE_LINE0_OUT DEF_LINE_WIDTH_0
+ #define DEF_DOUBLE_LINE0_IN DEF_LINE_WIDTH_0
+ #define DEF_DOUBLE_LINE0_DIST DEF_LINE_WIDTH_1
+
+ #define DEF_DOUBLE_LINE1_OUT DEF_LINE_WIDTH_1
+ #define DEF_DOUBLE_LINE1_IN DEF_LINE_WIDTH_1
+ #define DEF_DOUBLE_LINE1_DIST DEF_LINE_WIDTH_1
+
+ #define DEF_DOUBLE_LINE2_OUT DEF_LINE_WIDTH_2
+ #define DEF_DOUBLE_LINE2_IN DEF_LINE_WIDTH_2
+ #define DEF_DOUBLE_LINE2_DIST DEF_LINE_WIDTH_2
+
+ #define DEF_DOUBLE_LINE3_OUT DEF_LINE_WIDTH_2
+ #define DEF_DOUBLE_LINE3_IN DEF_LINE_WIDTH_1
+ #define DEF_DOUBLE_LINE3_DIST DEF_LINE_WIDTH_2
+
+ #define DEF_DOUBLE_LINE4_OUT DEF_LINE_WIDTH_1
+ #define DEF_DOUBLE_LINE4_IN DEF_LINE_WIDTH_2
+ #define DEF_DOUBLE_LINE4_DIST DEF_LINE_WIDTH_1
+
+ #define DEF_DOUBLE_LINE5_OUT DEF_LINE_WIDTH_3
+ #define DEF_DOUBLE_LINE5_IN DEF_LINE_WIDTH_2
+ #define DEF_DOUBLE_LINE5_DIST DEF_LINE_WIDTH_2
+
+ #define DEF_DOUBLE_LINE6_OUT DEF_LINE_WIDTH_2
+ #define DEF_DOUBLE_LINE6_IN DEF_LINE_WIDTH_3
+ #define DEF_DOUBLE_LINE6_DIST DEF_LINE_WIDTH_2
+
+ #define DEF_DOUBLE_LINE7_OUT DEF_LINE_WIDTH_0
+ #define DEF_DOUBLE_LINE7_IN DEF_LINE_WIDTH_0
+ #define DEF_DOUBLE_LINE7_DIST DEF_LINE_WIDTH_2
+
+ #define DEF_DOUBLE_LINE8_OUT DEF_LINE_WIDTH_1
+ #define DEF_DOUBLE_LINE8_IN DEF_LINE_WIDTH_0
+ #define DEF_DOUBLE_LINE8_DIST DEF_LINE_WIDTH_2
+
+ #define DEF_DOUBLE_LINE9_OUT DEF_LINE_WIDTH_2
+ #define DEF_DOUBLE_LINE9_IN DEF_LINE_WIDTH_0
+ #define DEF_DOUBLE_LINE9_DIST DEF_LINE_WIDTH_2
+
+ #define DEF_DOUBLE_LINE10_OUT DEF_LINE_WIDTH_3
+ #define DEF_DOUBLE_LINE10_IN DEF_LINE_WIDTH_0
+ #define DEF_DOUBLE_LINE10_DIST DEF_LINE_WIDTH_2
+ */
+ // Deklarationen gemaess BOXITEM.HXX
+ static const WW8_BordersSO aLineTabVer8[] =
+ {
+/* 0*/ { DEF_LINE_WIDTH_0, 0, 0 },
+/* 1*/ { DEF_LINE_WIDTH_1, 0, 0 },
+/* 2*/ { DEF_LINE_WIDTH_2, 0, 0 },
+/* 3*/ { DEF_LINE_WIDTH_3, 0, 0 },
+/* 4*/ { DEF_LINE_WIDTH_4, 0, 0 },
+/* 5*/ { DEF_LINE_WIDTH_5, 0, 0 },
+/* 6*/ { DEF_DOUBLE_LINE0_OUT, DEF_DOUBLE_LINE0_IN, DEF_DOUBLE_LINE0_DIST },
+/* 7*/ { DEF_DOUBLE_LINE1_OUT, DEF_DOUBLE_LINE1_IN, DEF_DOUBLE_LINE1_DIST },
+/* 8*/ { DEF_DOUBLE_LINE2_OUT, DEF_DOUBLE_LINE2_IN, DEF_DOUBLE_LINE2_DIST },
+/* 9*/ { DEF_DOUBLE_LINE3_OUT, DEF_DOUBLE_LINE3_IN, DEF_DOUBLE_LINE3_DIST },
+/*10*/ { DEF_DOUBLE_LINE4_OUT, DEF_DOUBLE_LINE4_IN, DEF_DOUBLE_LINE4_DIST },
+/*11*/ { DEF_DOUBLE_LINE5_OUT, DEF_DOUBLE_LINE5_IN, DEF_DOUBLE_LINE5_DIST },
+/*12*/ { DEF_DOUBLE_LINE6_OUT, DEF_DOUBLE_LINE6_IN, DEF_DOUBLE_LINE6_DIST },
+/*13*/ { DEF_DOUBLE_LINE7_OUT, DEF_DOUBLE_LINE7_IN, DEF_DOUBLE_LINE7_DIST },
+/*14*/ { DEF_DOUBLE_LINE8_OUT, DEF_DOUBLE_LINE8_IN, DEF_DOUBLE_LINE8_DIST },
+/*15*/ { DEF_DOUBLE_LINE9_OUT, DEF_DOUBLE_LINE9_IN, DEF_DOUBLE_LINE9_DIST },
+/*16*/ { DEF_DOUBLE_LINE10_OUT,DEF_DOUBLE_LINE10_IN,DEF_DOUBLE_LINE10_DIST}
+ };
+ size_t nPos = static_cast<size_t>(eCode);
+ ASSERT(nPos < sizeof(aLineTabVer8), "Impossible");
+ if (nPos >= sizeof(aLineTabVer8))
+ eCode = single0;
+ return aLineTabVer8[eCode];
+}
+
+sal_Int32 SwMSDffManager::GetEscherLineMatch(MSO_LineStyle eStyle,
+ MSO_SPT eShapeType, sal_Int32 &rThick)
+{
+ sal_Int32 nOutsideThick = 0;
+ /*
+ Beachte: im Gegensatz zu den Winword-ueblichen Tabellen- und
+ Rahmen-Randbreiten-Angaben, bei denen jeweils aus der Staerke *einer*
+ Linie die Gesamt-Randbreite zu errechnen ist, liegen die aus dem ESCHER
+ stammenden Daten bereits als Gesamt-Breite [twips] vor!
+
+ Der Winword default ist 15 tw. Wir nehmen hierfuer unsere 20 tw Linie. (
+ 0.75 pt uns 1.0 pt sehen sich auf dem Ausdruck naemlich aehnlicher als
+ etwas 0.75 pt und unsere 0.05 pt Haarlinie. ) Die Haarlinie setzen wir nur
+ bei Winword-Staerken bis zu maximal 0.5 pt ein.
+ */
+ switch( eStyle )
+ {
+ case mso_lineTriple:
+ case mso_lineSimple:
+ nOutsideThick = eShapeType != mso_sptTextBox ? rThick : rThick/2;
+ break;
+ case mso_lineDouble:
+ if (eShapeType == mso_sptTextBox)
+ {
+ nOutsideThick = rThick/6;
+ rThick = rThick*2/3;
+ }
+ else
+ nOutsideThick = rThick*2/3;
+ break;
+ case mso_lineThickThin:
+ if (eShapeType == mso_sptTextBox)
+ {
+ nOutsideThick = rThick*3/10;
+ rThick = rThick*4/5;
+ }
+ else
+ nOutsideThick = rThick*4/5;
+ break;
+ case mso_lineThinThick:
+ {
+ if (eShapeType == mso_sptTextBox)
+ {
+ nOutsideThick = rThick/10;
+ rThick = rThick*3/5;
+ }
+ else
+ nOutsideThick = rThick*3/5;
+ }
+ break;
+ default:
+ break;
+ }
+ return nOutsideThick;
+}
+
+//Returns the thickness of the line outside the frame, the logic of
+//words positioning of borders around floating objects is that of a
+//disturbed mind.
+sal_Int32 SwWW8ImplReader::MatchSdrBoxIntoFlyBoxItem(const Color& rLineColor,
+ MSO_LineStyle eLineStyle, MSO_SPT eShapeType, sal_Int32 &rLineThick,
+ SvxBoxItem& rBox )
+{
+ sal_Int32 nOutsideThick = 0;
+ if( !rLineThick )
+ return nOutsideThick;
+
+ WW8_BordersSO::eBorderCode nIdx = WW8_BordersSO::none;
+
+ sal_Int32 nLineThick=rLineThick;
+ nOutsideThick = SwMSDffManager::GetEscherLineMatch(eLineStyle,
+ eShapeType, rLineThick);
+
+ /*
+ Beachte: im Gegensatz zu den Winword-ueblichen Tabellen- und
+ Rahmen-Randbreiten-Angaben, bei denen jeweils aus der Staerke *einer*
+ Linie die Gesamt-Randbreite zu errechnen ist, liegen die aus dem ESCHER
+ stammenden Daten bereits als Gesamt-Breite [twips] vor!
+
+ Der Winword default ist 15 tw. Wir nehmen hierfuer unsere 20 tw Linie. (
+ 0.75 pt uns 1.0 pt sehen sich auf dem Ausdruck naemlich aehnlicher als
+ etwas 0.75 pt und unsere 0.05 pt Haarlinie. ) Die Haarlinie setzen wir nur
+ bei Winword-Staerken bis zu maximal 0.5 pt ein.
+ */
+ switch( +eLineStyle )
+ {
+ // zuerst die Einzel-Linien
+ case mso_lineSimple:
+ if (nLineThick < 10)
+ nIdx = WW8_BordersSO::single0;// 1 Twip bei uns
+ else if (nLineThick < 20)
+ nIdx = WW8_BordersSO::single5;// 10 Twips bei uns
+ else if (nLineThick < 50)
+ nIdx = WW8_BordersSO::single1;// 20 Twips
+ else if (nLineThick < 80)
+ nIdx = WW8_BordersSO::single2;// 50
+ else if (nLineThick < 100)
+ nIdx = WW8_BordersSO::single3;// 80
+ else if (nLineThick <150)
+ nIdx = WW8_BordersSO::single4;// 100
+ // Pfusch: fuer die ganz dicken Linien muessen wir doppelte Linien
+ // malen, weil unsere Einfach-Linie nicht dicker als 5 Punkt wird
+ else if (nLineThick <180)
+ nIdx = WW8_BordersSO::double2;// 150
+ else
+ nIdx = WW8_BordersSO::double5;// 180
+ break;
+ // dann die Doppel-Linien, fuer die wir feine Entsprechungen haben :-)))
+ case mso_lineDouble:
+ if (nLineThick < 60)
+ nIdx = WW8_BordersSO::double0;// 22 Twips bei uns
+ else if (nLineThick < 135)
+ nIdx = WW8_BordersSO::double7;// some more space
+ else if (nLineThick < 180)
+ nIdx = WW8_BordersSO::double1;// 60
+ else
+ nIdx = WW8_BordersSO::double2;// 150
+ break;
+ case mso_lineThickThin:
+ if (nLineThick < 87)
+ nIdx = WW8_BordersSO::double8;// 71 Twips bei uns
+ else if (nLineThick < 117)
+ nIdx = WW8_BordersSO::double9;// 101
+ else if (nLineThick < 166)
+ nIdx = WW8_BordersSO::double10;// 131
+ else
+ nIdx = WW8_BordersSO::double5;// 180
+ break;
+ case mso_lineThinThick:
+ if (nLineThick < 137)
+ nIdx = WW8_BordersSO::double4;// 90 Twips bei uns
+ else
+ nIdx = WW8_BordersSO::double6;// 180
+ break;
+ // zu guter Letzt die Dreifach-Linien, an deren Stelle wir eine
+ // Doppel-Linie setzen
+ case mso_lineTriple:
+ if (nLineThick < 46)
+ nIdx = WW8_BordersSO::double0;// 22 Twips bei uns
+ else if (nLineThick < 106)
+ nIdx = WW8_BordersSO::double1;// 60
+ else if (nLineThick < 166)
+ nIdx = WW8_BordersSO::double2;// 150
+ else
+ nIdx = WW8_BordersSO::double5;// 180
+ break;
+ // no line style is set
+ case (MSO_LineStyle)USHRT_MAX:
+ break;
+ // erroneously not implemented line style is set
+ default:
+ ASSERT(!this, "eLineStyle is not (yet) implemented!");
+ break;
+ }
+
+ if (WW8_BordersSO::none != nIdx)
+ {
+ SvxBorderLine aLine;
+ aLine.SetColor( rLineColor );
+
+ const WW8_BordersSO& rBorders = WW8_BordersSO::Get0x01LineMatch(nIdx);
+
+ aLine.SetOutWidth(rBorders.mnOut);
+ aLine.SetInWidth (rBorders.mnIn);
+ aLine.SetDistance(rBorders.mnDist);
+
+ for(sal_uInt16 nLine = 0; nLine < 4; ++nLine)
+ rBox.SetLine(new SvxBorderLine( aLine ), nLine);
+ }
+
+ return nOutsideThick;
+}
+
+#define WW8ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue()
+
+void SwWW8ImplReader::MatchSdrItemsIntoFlySet( SdrObject* pSdrObj,
+ SfxItemSet& rFlySet, MSO_LineStyle eLineStyle, MSO_SPT eShapeType,
+ Rectangle& rInnerDist )
+{
+/*
+ am Rahmen zu setzende Frame-Attribute
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ SwFmtFrmSize falls noch nicht gesetzt, hier setzen
+ SvxLRSpaceItem hier setzen
+ SvxULSpaceItem hier setzen
+ SvxOpaqueItem (Derzeit bei Rahmen nicht moeglich! khz 10.2.1999)
+ SwFmtSurround bereits gesetzt
+ SwFmtVertOrient bereits gesetzt
+ SwFmtHoriOrient bereits gesetzt
+ SwFmtAnchor bereits gesetzt
+ SvxBoxItem hier setzen
+ SvxBrushItem hier setzen
+ SvxShadowItem hier setzen
+*/
+
+ // 1. GrafikObjekt des Docs?
+ GrafikCtor();
+
+ const SfxItemSet& rOldSet = pSdrObj->GetMergedItemSet();
+
+ // einige Items koennen direkt so uebernommen werden
+ const sal_uInt16 nDirectMatch = 2;
+ static RES_FRMATR __READONLY_DATA aDirectMatch[ nDirectMatch ] =
+ {
+ RES_LR_SPACE, // Aussenabstand links/rechts: SvxLRSpaceItem
+ RES_UL_SPACE // Aussenabstand Oben/unten: SvxULSpaceItem
+ };
+ const SfxPoolItem* pPoolItem;
+ for(sal_uInt16 nItem = 0; nItem < nDirectMatch; ++nItem)
+ if( SFX_ITEM_SET == rOldSet.GetItemState(
+ static_cast< sal_uInt16 >(aDirectMatch[ nItem ]), false, &pPoolItem) )
+ {
+ rFlySet.Put( *pPoolItem );
+ }
+
+
+ // jetzt die Umrandung berechnen und die Box bauen: Das Mass wird fuer die
+ // Rahmen-GROESSE benoetigt!
+ SvxBoxItem aBox(sw::util::ItemGet<SvxBoxItem>(rFlySet, RES_BOX));
+ // dashed oder solid wird zu solid
+ sal_Int32 nLineThick = 0, nOutside=0;
+
+ // check if LineStyle is *really* set!
+ const SfxPoolItem* pItem;
+
+ SfxItemState eState = rOldSet.GetItemState(XATTR_LINESTYLE,true,&pItem);
+ if( eState == SFX_ITEM_SET )
+ {
+ // Now, that we know there is a line style we will make use the
+ // parameter given to us when calling the method... :-)
+ const Color aLineColor = static_cast< XLineColorItem const & >(
+ rOldSet.Get(XATTR_LINECOLOR)).GetColorValue();
+ nLineThick = WW8ITEMVALUE(rOldSet, XATTR_LINEWIDTH, XLineWidthItem);
+
+ if( !nLineThick )
+ nLineThick = 15; // WW-default: 0.75 pt
+
+ nOutside = MatchSdrBoxIntoFlyBoxItem(aLineColor, eLineStyle,
+ eShapeType, nLineThick, aBox);
+ }
+
+ rInnerDist.Left()+=nLineThick;
+ rInnerDist.Top()+=nLineThick;
+ rInnerDist.Right()+=nLineThick;
+ rInnerDist.Bottom()+=nLineThick;
+
+ const SvxBorderLine *pLine;
+ if (0 != (pLine = aBox.GetLine(BOX_LINE_LEFT)))
+ {
+ rInnerDist.Left() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
+ pLine->GetDistance());
+ }
+
+ if (0 != (pLine = aBox.GetLine(BOX_LINE_TOP)))
+ {
+ rInnerDist.Top() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
+ pLine->GetDistance());
+ }
+
+ if (0 != (pLine = aBox.GetLine(BOX_LINE_RIGHT)))
+ {
+ rInnerDist.Right() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
+ pLine->GetDistance());
+ }
+
+ if (0 != (pLine = aBox.GetLine(BOX_LINE_BOTTOM)))
+ {
+ rInnerDist.Bottom() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
+ pLine->GetDistance());
+ }
+
+ // set distances from box's border to text contained within the box
+ if( 0 < rInnerDist.Left() )
+ aBox.SetDistance( (sal_uInt16)rInnerDist.Left(), BOX_LINE_LEFT );
+ if( 0 < rInnerDist.Top() )
+ aBox.SetDistance( (sal_uInt16)rInnerDist.Top(), BOX_LINE_TOP );
+ if( 0 < rInnerDist.Right() )
+ aBox.SetDistance( (sal_uInt16)rInnerDist.Right(), BOX_LINE_RIGHT );
+ if( 0 < rInnerDist.Bottom() )
+ aBox.SetDistance( (sal_uInt16)rInnerDist.Bottom(), BOX_LINE_BOTTOM );
+
+ bool bFixSize = !(WW8ITEMVALUE(rOldSet, SDRATTR_TEXT_AUTOGROWHEIGHT,
+ SdrTextAutoGrowHeightItem));
+
+ // Size: SwFmtFrmSize
+ if( SFX_ITEM_SET != rFlySet.GetItemState(RES_FRM_SIZE, false) )
+ {
+ const Rectangle& rSnapRect = pSdrObj->GetSnapRect();
+ // if necessary adapt width and position of the framework: The
+ // recorded interior is to remain equally large despite thick edges.
+ rFlySet.Put( SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE,
+ rSnapRect.GetWidth() + 2*nOutside,
+ rSnapRect.GetHeight() + 2*nOutside) );
+ }
+ else //If a size is set, adjust it to consider border thickness
+ {
+ SwFmtFrmSize aSize = (const SwFmtFrmSize &)(rFlySet.Get(RES_FRM_SIZE));
+
+ SwFmtFrmSize aNewSize = SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE,
+ aSize.GetWidth() + 2*nOutside,
+ aSize.GetHeight() + 2*nOutside);
+ aNewSize.SetWidthSizeType(aSize.GetWidthSizeType());
+ rFlySet.Put( aNewSize );
+ }
+
+ //Sadly word puts escher borders outside the graphic, but orients the
+ //graphic in relation to the top left inside the border. We don't
+ if (nOutside)
+ {
+ SwFmtHoriOrient aHori = (const SwFmtHoriOrient &)(rFlySet.Get(
+ RES_HORI_ORIENT));
+ aHori.SetPos(MakeSafePositioningValue(aHori.GetPos()-nOutside));
+ rFlySet.Put(aHori);
+
+ SwFmtVertOrient aVert = (const SwFmtVertOrient &)(rFlySet.Get(
+ RES_VERT_ORIENT));
+ aVert.SetPos(aVert.GetPos()-nOutside);
+ rFlySet.Put(aVert);
+ }
+
+ // jetzt die Umrandung setzen
+ rFlySet.Put( aBox );
+
+ // Schattenwurf der Box: SvxShadowItem
+ if( WW8ITEMVALUE(rOldSet, SDRATTR_SHADOW, SdrShadowItem) )
+ {
+ SvxShadowItem aShadow( RES_SHADOW );
+
+ const Color aShdColor = static_cast< SdrShadowColorItem const & >(
+ rOldSet.Get(SDRATTR_SHADOWCOLOR)).GetColorValue();
+ const sal_Int32 nShdDistX = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWXDIST,
+ SdrShadowXDistItem);
+ const sal_Int32 nShdDistY = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWYDIST,
+ SdrShadowYDistItem);
+ //const sal_uInt16 nShdTrans= WW8ITEMVALUE(rOldSet,
+ // SDRATTR_SHADOWTRANSPARENCE, SdrShadowTransparenceItem);
+
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ //
+ // SfxVoidItem( SDRATTR_SHADOW3D )
+ // SfxVoidItem( SDRATTR_SHADOWPERSP )
+
+ aShadow.SetColor( Color( aShdColor ) );
+
+ aShadow.SetWidth(writer_cast<sal_uInt16>((Abs( nShdDistX) +
+ Abs( nShdDistY )) / 2 ));
+
+ SvxShadowLocation eShdPosi;
+ if( 0 <= nShdDistX )
+ {
+ if( 0 <= nShdDistY )
+ eShdPosi = SVX_SHADOW_BOTTOMRIGHT;
+ else
+ eShdPosi = SVX_SHADOW_TOPRIGHT;
+ }
+ else
+ {
+ if( 0 <= nShdDistY )
+ eShdPosi = SVX_SHADOW_BOTTOMLEFT;
+ else
+ eShdPosi = SVX_SHADOW_TOPLEFT;
+ }
+ aShadow.SetLocation( eShdPosi );
+
+ rFlySet.Put( aShadow );
+ }
+ Color Temp(COL_WHITE);
+ SvxBrushItem aBrushItem(Temp, RES_BACKGROUND);
+ bool bBrushItemOk = false;
+ sal_uInt8 nTrans = 0;
+
+ //Seperate transparency
+ eState = rOldSet.GetItemState(XATTR_FILLTRANSPARENCE, true, &pItem);
+ if (eState == SFX_ITEM_SET)
+ {
+ sal_uInt16 nRes = WW8ITEMVALUE(rOldSet, XATTR_FILLTRANSPARENCE,
+ XFillTransparenceItem);
+ nTrans = sal_uInt8((nRes * 0xFE) / 100);
+ aBrushItem.GetColor().SetTransparency(nTrans);
+ bBrushItemOk = true;
+ }
+
+ // Hintergrund: SvxBrushItem
+ eState = rOldSet.GetItemState(XATTR_FILLSTYLE, true, &pItem);
+ if (eState == SFX_ITEM_SET)
+ {
+ const XFillStyle eFill = ((const XFillStyleItem*)pItem)->GetValue();
+
+ switch (eFill)
+ {
+ case XFILL_NONE:
+ //Writer graphics don't have it yet
+ if (eShapeType != mso_sptPictureFrame)
+ {
+ aBrushItem.GetColor().SetTransparency(0xFE);
+ bBrushItemOk = true;
+ }
+ break;
+ case XFILL_SOLID:
+ {
+ const Color aColor = static_cast< XFillColorItem const & >(
+ rOldSet.Get(XATTR_FILLCOLOR)).GetColorValue();
+ aBrushItem.SetColor(aColor);
+
+ if (bBrushItemOk) //has trans
+ aBrushItem.GetColor().SetTransparency(nTrans);
+
+ bBrushItemOk = true;
+ }
+ break;
+ case XFILL_GRADIENT:
+ break;
+ case XFILL_HATCH:
+ break;
+ case XFILL_BITMAP:
+ {
+ const Graphic aGraphic(
+ static_cast< XFillBitmapItem const & >(
+ rOldSet.Get(XATTR_FILLBITMAP)).
+ GetBitmapValue().GetBitmap());
+ bool bTile = WW8ITEMVALUE(rOldSet, XATTR_FILLBMP_TILE,
+ SfxBoolItem) ? true: false;
+ GraphicObject aGrfObj(aGraphic);
+
+ aBrushItem.SetGraphicObject(aGrfObj);
+
+ if (bBrushItemOk) //has trans
+ {
+ GraphicObject *pGraphicObject =
+ const_cast<GraphicObject *>
+ (aBrushItem.GetGraphicObject());
+ GraphicAttr aAttr(pGraphicObject->GetAttr());
+ aAttr.SetTransparency(nTrans);
+ pGraphicObject->SetAttr(aAttr);
+ }
+
+ aBrushItem.SetGraphicPos(bTile ? GPOS_TILED : GPOS_AREA);
+
+ bBrushItemOk = true;
+ }
+ break;
+ }
+ }
+
+ if (bBrushItemOk)
+ rFlySet.Put(aBrushItem, RES_BACKGROUND);
+}
+
+void SwWW8ImplReader::AdjustLRWrapForWordMargins(
+ const SvxMSDffImportRec &rRecord, SvxLRSpaceItem &rLR)
+{
+ // Left adjustments - if horizontally aligned to left of
+ // margin or column then remove the left wrapping
+ if (rRecord.nXAlign == 1)
+ {
+ if ((rRecord.nXRelTo == 0) || (rRecord.nXRelTo == 2))
+ rLR.SetLeft((sal_uInt16)0);
+ }
+
+ // Right adjustments - if horizontally aligned to right of
+ // margin or column then remove the right wrapping
+ if (rRecord.nXAlign == 3)
+ {
+ if ((rRecord.nXRelTo == 0) || (rRecord.nXRelTo == 2))
+ rLR.SetRight((sal_uInt16)0);
+ }
+
+ //Inside margin, remove left wrapping
+ if ((rRecord.nXAlign == 4) && (rRecord.nXRelTo == 0))
+ {
+ rLR.SetLeft((sal_uInt16)0);
+ }
+
+ //Outside margin, remove left wrapping
+ if ((rRecord.nXAlign == 5) && (rRecord.nXRelTo == 0))
+ {
+ rLR.SetRight((sal_uInt16)0);
+ }
+}
+
+
+void SwWW8ImplReader::AdjustULWrapForWordMargins(
+ const SvxMSDffImportRec &rRecord, SvxULSpaceItem &rUL)
+{
+ // Top adjustment - remove upper wrapping if aligned to page
+ // printable area or to page
+ if (rRecord.nYAlign == 1)
+ {
+ if ((rRecord.nYRelTo == 0) || (rRecord.nYRelTo == 1))
+ rUL.SetUpper((sal_uInt16)0);
+ }
+
+ // Bottom adjustment - remove bottom wrapping if aligned to page or
+ // printable area or to page
+ if (rRecord.nYAlign == 3)
+ {
+ if ((rRecord.nYRelTo == 0) || (rRecord.nYRelTo == 1))
+ rUL.SetLower((sal_uInt16)0);
+ }
+
+ //Remove top margin if aligned vertically inside margin
+ if ((rRecord.nYAlign == 4) && (rRecord.nYRelTo == 0))
+ rUL.SetUpper((sal_uInt16)0);
+
+ /*
+ // Something like this needs to be done once inside and outside are
+ // fixed
+ if (rRecord.nYAlign == 4)
+ {
+ if (rRecord.nYRelTo == 0)
+ rUL.SetUpper((sal_uInt16)0);
+ }
+ */
+}
+
+void SwWW8ImplReader::MapWrapIntoFlyFmt(SvxMSDffImportRec* pRecord,
+ SwFrmFmt* pFlyFmt)
+{
+ if (!pRecord || !pFlyFmt)
+ return;
+
+ if (pRecord->nDxWrapDistLeft || pRecord->nDxWrapDistRight)
+ {
+ SvxLRSpaceItem aLR(writer_cast<sal_uInt16>(pRecord->nDxWrapDistLeft),
+ writer_cast<sal_uInt16>(pRecord->nDxWrapDistRight), 0, 0, RES_LR_SPACE);
+ AdjustLRWrapForWordMargins(*pRecord, aLR);
+ pFlyFmt->SetFmtAttr(aLR);
+ }
+ if (pRecord->nDyWrapDistTop || pRecord->nDyWrapDistBottom)
+ {
+ SvxULSpaceItem aUL(writer_cast<sal_uInt16>(pRecord->nDyWrapDistTop),
+ writer_cast<sal_uInt16>(pRecord->nDyWrapDistBottom), RES_UL_SPACE);
+ AdjustULWrapForWordMargins(*pRecord, aUL);
+ pFlyFmt->SetFmtAttr(aUL);
+ }
+
+ //If we are contoured and have a custom polygon...
+ if (pRecord->pWrapPolygon && pFlyFmt->GetSurround().IsContour())
+ {
+ if (SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(*pFlyFmt))
+ {
+
+ /*
+ Gather round children and hear of a tale that will raise the
+ hairs on the back of your neck this dark halloween night.
+
+ There is a polygon in word that describes the wraping around
+ the graphic.
+
+ Here are some sample values for the simplest case of a square
+ around some solid coloured graphics
+
+ X Y Pixel size of graphic
+ TopLeft -54 21600 400x400
+ Bottom Right 0 21546
+
+ TopLeft -108 21600 200x200
+ Bottom Right 0 21492
+
+ TopLeft -216 21600 100x100
+ Bottom Right 0 21384
+
+ TopLeft -432 21600 50x50
+ Bottom Right 0 21168
+
+ TopLeft -76 21600 283x212
+ Bottom Right 0 21498
+
+ So given that the size of the values remains pretty much the
+ same despite the size of the graphic, we can tell that the
+ polygon is measured in units that are independant of the
+ graphic. But why does the left corner move a different value
+ to the left each time, and why does the bottom move upwards
+ each time, when the right and top remain at the same value ?
+
+ I have no idea, but clearly once we calculate the values out
+ we see that the left margin is always a fixed realworld
+ distance from the true left and the polygon bottom is the same
+ fixed value from the bottom. i.e. 15twips.
+
+ So here we take our word provided polygon, shift it to the
+ right by 15twips and rescale it widthwise to shrink the width
+ a little to fit the now moved right margin back to where it
+ was, and stretch the height a little to make the bottom move
+ down the missing 15twips then we get a polygon that matches
+ what I actually see in word
+ */
+
+ PolyPolygon aPoly(*pRecord->pWrapPolygon);
+ const Size &rSize = pNd->GetTwipSize();
+ /*
+ Move to the left by 15twips, and rescale to
+ a) shrink right bound back to orig position
+ b) stretch bottom bound to where I think it should have been
+ in the first place
+ */
+ Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
+ aMoveHack *= Fraction(15, 1);
+ long nMove(aMoveHack);
+ aPoly.Move(nMove, 0);
+
+ Fraction aHackX(ww::nWrap100Percent, ww::nWrap100Percent + nMove);
+ Fraction aHackY(ww::nWrap100Percent, ww::nWrap100Percent - nMove);
+ aPoly.Scale(aHackX, aHackY);
+
+ //Turn polygon back into units that match the graphic's
+ const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
+ Fraction aMapPolyX(rOrigSize.Width(), ww::nWrap100Percent);
+ Fraction aMapPolyY(rOrigSize.Height(), ww::nWrap100Percent);
+ aPoly.Scale(aMapPolyX, aMapPolyY);
+
+ // --> OD 2005-05-19 #i47277# - contour is already in unit of the
+ // graphic prefered unit. Thus, call method <SetContour(..)>
+ pNd->SetContour(&aPoly);
+ // <--
+ }
+ }
+}
+
+void SwWW8ImplReader::SetAttributesAtGrfNode( SvxMSDffImportRec* pRecord,
+ SwFrmFmt *pFlyFmt, WW8_FSPA *pF )
+{
+ const SwNodeIndex* pIdx = pFlyFmt->GetCntnt(false).GetCntntIdx();
+ SwGrfNode* pGrfNd;
+ if( pIdx && 0 != (pGrfNd = rDoc.GetNodes()[pIdx->GetIndex() + 1]->GetGrfNode() ))
+ {
+ Size aSz(pGrfNd->GetTwipSize());
+ // --> OD 2005-08-01 #124722# - use type <sal_uInt64> instead of <sal_uLong>
+ // to get correct results in the following calculations.
+ sal_uInt64 rHeight = aSz.Height();
+ sal_uInt64 rWidth = aSz.Width();
+ // <--
+ if( !rWidth && pF)
+ rWidth = pF->nXaRight - pF->nXaLeft;
+ else if( !rHeight && pF)
+ rHeight = pF->nYaBottom - pF->nYaTop;
+
+ if( pRecord->nCropFromTop || pRecord->nCropFromBottom ||
+ pRecord->nCropFromLeft || pRecord->nCropFromRight )
+ {
+ SwCropGrf aCrop; // Cropping is stored in 'fixed floats'
+ // 16.16 (it est fraction times total
+ if( pRecord->nCropFromTop ) // image width or height resp.)
+ aCrop.SetTop( static_cast< sal_Int32 >(
+ ( ( (pRecord->nCropFromTop >> 16 ) * rHeight )
+ + (((pRecord->nCropFromTop & 0xffff) * rHeight ) >> 16) )));
+ if( pRecord->nCropFromBottom )
+ aCrop.SetBottom( static_cast< sal_Int32 >(
+ ( ( (pRecord->nCropFromBottom >> 16 ) * rHeight )
+ + (((pRecord->nCropFromBottom & 0xffff) * rHeight ) >> 16) )));
+ if( pRecord->nCropFromLeft )
+ aCrop.SetLeft( static_cast< sal_Int32 >(
+ ( ( (pRecord->nCropFromLeft >> 16 ) * rWidth )
+ + (((pRecord->nCropFromLeft & 0xffff) * rWidth ) >> 16) )));
+ if( pRecord->nCropFromRight )
+ aCrop.SetRight( static_cast< sal_Int32 >(
+ ( ( (pRecord->nCropFromRight >> 16 ) * rWidth )
+ + (((pRecord->nCropFromRight & 0xffff) * rWidth ) >> 16) )));
+
+ pGrfNd->SetAttr( aCrop );
+ }
+
+ if (pRecord && pRecord->pObj)
+ {
+ const SfxItemSet& rOldSet = pRecord->pObj->GetMergedItemSet();
+ //contrast
+ if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFCONTRAST,
+ SdrGrafContrastItem))
+ {
+ SwContrastGrf aContrast(
+ WW8ITEMVALUE(rOldSet,
+ SDRATTR_GRAFCONTRAST, SdrGrafContrastItem));
+ pGrfNd->SetAttr( aContrast );
+ }
+
+ //luminance
+ if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFLUMINANCE,
+ SdrGrafLuminanceItem))
+ {
+ SwLuminanceGrf aLuminance(WW8ITEMVALUE(rOldSet,
+ SDRATTR_GRAFLUMINANCE, SdrGrafLuminanceItem));
+ pGrfNd->SetAttr( aLuminance );
+ }
+ //gamma
+ if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA, SdrGrafGamma100Item))
+ {
+ double fVal = WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA,
+ SdrGrafGamma100Item);
+ pGrfNd->SetAttr(SwGammaGrf(fVal/100.));
+ }
+
+ //drawmode
+ if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFMODE, SdrGrafModeItem))
+ {
+ SwDrawModeGrf aDrawMode( static_cast< sal_uInt16 >(WW8ITEMVALUE(rOldSet,
+ SDRATTR_GRAFMODE, SdrGrafModeItem)) );
+ pGrfNd->SetAttr( aDrawMode );
+ }
+ }
+ }
+}
+
+SdrObject* SwWW8ImplReader::CreateContactObject(SwFrmFmt* pFlyFmt)
+{
+ if (pFlyFmt)
+ {
+ //JP 11.1.2002: task 96329
+ SdrObject* pNewObject = mbNewDoc ? 0 : pFlyFmt->FindRealSdrObject();
+ if (!pNewObject)
+ pNewObject = pFlyFmt->FindSdrObject();
+ if (!pNewObject && pFlyFmt->ISA(SwFlyFrmFmt))
+ {
+ SwFlyDrawContact* pContactObject
+ = new SwFlyDrawContact(static_cast<SwFlyFrmFmt*>(pFlyFmt),
+ pDrawModel);
+ pNewObject = pContactObject->GetMaster();
+ }
+ return pNewObject;
+ }
+ return 0;
+}
+
+//#109311# Miserable miserable hack to fudge word's graphic layout in
+//RTL mode to ours.
+bool SwWW8ImplReader::MiserableRTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
+ sal_Int16 eHoriOri, sal_Int16 eHoriRel)
+{
+ if (!IsRightToLeft())
+ return false;
+ return RTLGraphicsHack(rLeft, nWidth, eHoriOri, eHoriRel,
+ maSectionManager.GetPageLeft(),
+ maSectionManager.GetPageRight(),
+ maSectionManager.GetPageWidth());
+}
+
+RndStdIds SwWW8ImplReader::ProcessEscherAlign(SvxMSDffImportRec* pRecord,
+ WW8_FSPA *pFSPA, SfxItemSet &rFlySet, bool /*bOrgObjectWasReplace*/)
+{
+ ASSERT(pRecord || pFSPA, "give me something! to work with for anchoring");
+ if (!pRecord && !pFSPA)
+ return FLY_AT_PAGE;
+
+ SvxMSDffImportRec aRecordFromFSPA;
+ if (!pRecord)
+ {
+ pRecord = &aRecordFromFSPA;
+ pRecord->nXRelTo = pFSPA->nbx;
+ pRecord->nYRelTo = pFSPA->nby;
+ }
+
+ // nXAlign - abs. Position, Left, Centered, Right, Inside, Outside
+ // nYAlign - abs. Position, Top, Centered, Bottom, Inside, Outside
+
+ // nXRelTo - Page printable area, Page, Column, Character
+ // nYRelTo - Page printable area, Page, Paragraph, Line
+
+ const sal_uInt32 nCntXAlign = 6;
+ const sal_uInt32 nCntYAlign = 6;
+
+ const sal_uInt32 nCntRelTo = 4;
+
+ sal_uInt32 nXAlign = nCntXAlign > pRecord->nXAlign ? pRecord->nXAlign : 1;
+ sal_uInt32 nYAlign = nCntYAlign > pRecord->nYAlign ? pRecord->nYAlign : 1;
+
+ if (pFSPA)
+ {
+ /*
+ #74188# #i15718# #i19008#
+ Strangely in this case the FSPA value seems to be considered before
+ the newer escher nXRelTo record.
+ */
+ // --> OD 2005-08-04 #i52565# - correct condition checking:
+ // first check, if <nXRelTo> and <nYRelTo> have default values. This
+ // is a hint that these values aren't set by the escher import - see
+ // method <SwMSDffManager::ProcessObj(..)>. Then, check if for each
+ // values, if it differs from the one in the FSPA.
+ if ( pRecord->nXRelTo == 2 && pRecord->nYRelTo == 2 )
+ {
+ // if <nYRelTo> differs from <FSPA.nby> overwrite <nYRelTo>
+ if ( pFSPA->nby != pRecord->nYRelTo )
+ {
+ pRecord->nYRelTo = pFSPA->nby;
+ }
+ }
+ // <--
+ }
+
+ sal_uInt32 nXRelTo = nCntRelTo > pRecord->nXRelTo ? pRecord->nXRelTo : 1;
+ sal_uInt32 nYRelTo = nCntRelTo > pRecord->nYRelTo ? pRecord->nYRelTo : 1;
+
+ // --> OD 2005-03-03 #i43718#
+ RndStdIds eAnchor = IsInlineEscherHack() ? FLY_AS_CHAR : FLY_AT_CHAR;
+ // <--
+
+ SwFmtAnchor aAnchor( eAnchor );
+ aAnchor.SetAnchor( pPaM->GetPoint() );
+ rFlySet.Put( aAnchor );
+
+ if (pFSPA)
+ {
+ // OD 14.10.2003 #i18732#
+ //Given new layout where everything is changed to be anchored to
+ //character the following 4 tables may need to be changed.
+
+ // horizontal Adjustment
+ static const sal_Int16 aHoriOriTab[ nCntXAlign ] =
+ {
+ text::HoriOrientation::NONE, // From left position
+ text::HoriOrientation::LEFT, // left
+ text::HoriOrientation::CENTER, // centered
+ text::HoriOrientation::RIGHT, // right
+ // --> OD 2004-12-06 #i36649#
+ // - inside -> text::HoriOrientation::LEFT and outside -> text::HoriOrientation::RIGHT
+ text::HoriOrientation::LEFT, // inside
+ text::HoriOrientation::RIGHT // outside
+ // <--
+ };
+
+
+ // generic vertical Adjustment
+ static const sal_Int16 aVertOriTab[ nCntYAlign ] =
+ {
+ text::VertOrientation::NONE, // From Top position
+ text::VertOrientation::TOP, // top
+ text::VertOrientation::CENTER, // centered
+ text::VertOrientation::BOTTOM, // bottom
+ text::VertOrientation::LINE_TOP, // inside (obscure)
+ text::VertOrientation::LINE_BOTTOM // outside (obscure)
+ };
+
+ // CMC,OD 24.11.2003 #i22673# - to-line vertical alignment
+ static const sal_Int16 aToLineVertOriTab[ nCntYAlign ] =
+ {
+ text::VertOrientation::NONE, // below
+ text::VertOrientation::LINE_BOTTOM, // top
+ text::VertOrientation::LINE_CENTER, // centered
+ text::VertOrientation::LINE_TOP, // bottom
+ text::VertOrientation::LINE_BOTTOM, // inside (obscure)
+ text::VertOrientation::LINE_TOP // outside (obscure)
+ };
+
+ // Adjustment is horizontally relative to...
+ static const sal_Int16 aHoriRelOriTab[nCntRelTo] =
+ {
+ text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
+ text::RelOrientation::PAGE_FRAME, // 1 is page margin
+ text::RelOrientation::FRAME, // 2 is relative to column
+ text::RelOrientation::CHAR // 3 is relative to character
+ };
+
+ // Adjustment is vertically relative to...
+ // CMC, OD 24.11.2003 #i22673# - adjustment for new vertical alignment
+ // at top of line.
+ static const sal_Int16 aVertRelOriTab[nCntRelTo] =
+ {
+ text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
+ text::RelOrientation::PAGE_FRAME, // 1 is page margin
+ text::RelOrientation::FRAME, // 2 is relative to paragraph
+ text::RelOrientation::TEXT_LINE // 3 is relative to line
+ };
+
+ sal_Int16 eHoriOri = aHoriOriTab[ nXAlign ];
+ sal_Int16 eHoriRel = aHoriRelOriTab[ nXRelTo ];
+
+ // --> OD 2004-12-06 #i36649# - adjustments for certain alignments
+ if ( eHoriOri == text::HoriOrientation::LEFT && eHoriRel == text::RelOrientation::PAGE_FRAME )
+ {
+ // convert 'left to page' to 'from left -<width> to page text area'
+ eHoriOri = text::HoriOrientation::NONE;
+ eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
+ const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
+ pFSPA->nXaLeft = -nWidth;
+ pFSPA->nXaRight = 0;
+ }
+ else if ( eHoriOri == text::HoriOrientation::RIGHT && eHoriRel == text::RelOrientation::PAGE_FRAME )
+ {
+ // convert 'right to page' to 'from left 0 to right page border'
+ eHoriOri = text::HoriOrientation::NONE;
+ eHoriRel = text::RelOrientation::PAGE_RIGHT;
+ const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
+ pFSPA->nXaLeft = 0;
+ pFSPA->nXaRight = nWidth;
+ }
+ // <--
+
+ // --> OD 2005-02-07 #i24255# - position of floating screen objects in
+ // R2L layout are given in L2R layout, thus convert them of all
+ // floating screen objects, which are imported.
+ {
+ //#109311# Miserable miserable hack.
+ SwTwips nWidth = (pFSPA->nXaRight - pFSPA->nXaLeft);
+ SwTwips nLeft = pFSPA->nXaLeft;
+ if (MiserableRTLGraphicsHack(nLeft, nWidth, eHoriOri,
+ eHoriRel))
+ {
+ pFSPA->nXaLeft = nLeft;
+ pFSPA->nXaRight = pFSPA->nXaLeft + nWidth;
+ }
+ }
+ // <--
+
+ // --> OD 2005-01-20 #118546# - if the object is anchored inside
+ // a table cell, is horizontal aligned at frame|character and
+ // has wrap through, but its attribute 'layout in table cell' isn't set,
+ // convert its horizontal alignment to page text area.
+ // --> OD 2008-04-10 #i84783# - use new method <IsObjectLayoutInTableCell()>
+ if ( nInTable &&
+ ( eHoriRel == text::RelOrientation::FRAME || eHoriRel == text::RelOrientation::CHAR ) &&
+ pFSPA->nwr == 3 &&
+// pRecord->nLayoutInTableCell == 0x80000000 )
+ !IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell ) )
+ {
+ eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
+ }
+ // <--
+
+ SwFmtHoriOrient aHoriOri(MakeSafePositioningValue(pFSPA->nXaLeft),
+ eHoriOri, eHoriRel);
+ if( 4 <= nXAlign )
+ aHoriOri.SetPosToggle(true);
+ rFlySet.Put( aHoriOri );
+
+ //Writer honours this wrap distance when aligned as "left" or "right",
+ //Word doesn't. Writer doesn't honour it when its "from left".
+ if (eHoriOri == text::HoriOrientation::LEFT)
+ pRecord->nDxWrapDistLeft=0;
+ else if (eHoriOri == text::HoriOrientation::RIGHT)
+ pRecord->nDxWrapDistRight=0;
+
+ sal_Int16 eVertRel;
+ // OD 14.10.2003 #i18732#
+ eVertRel = aVertRelOriTab[ nYRelTo ];
+ // CMC, OD 24.11.2003 #i22673# - fill <eVertOri> in dependence of <eVertRel>
+ sal_Int16 eVertOri;
+ if ( eVertRel == text::RelOrientation::TEXT_LINE )
+ {
+ eVertOri = aToLineVertOriTab[ nYAlign ];
+ }
+ else
+ {
+ eVertOri = aVertOriTab[ nYAlign ];
+ }
+
+ //Below line in word is a positive value, while in writer its
+ //negative
+ long nYPos = pFSPA->nYaTop;
+ // CMC, OD 24.11.2003 #i22673#
+ if ((eVertRel == text::RelOrientation::TEXT_LINE) && (eVertOri == text::VertOrientation::NONE))
+ nYPos = -nYPos;
+
+ rFlySet.Put(SwFmtVertOrient(MakeSafePositioningValue(nYPos),
+ eVertOri, eVertRel));
+
+ if (
+ (pFSPA->nYaTop < 0) && (eVertOri == text::VertOrientation::NONE) &&
+ ((eAnchor == FLY_AT_PARA) || (eAnchor == FLY_AT_CHAR))
+ )
+ {
+ maTracer.Log(sw::log::eNegativeVertPlacement);
+ }
+ }
+
+ return eAnchor;
+}
+
+// --> OD 2008-04-10 #i84783#
+bool SwWW8ImplReader::IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTableCell ) const
+{
+ bool bIsObjectLayoutInTableCell = false;
+
+ if ( bVer8 )
+ {
+ const sal_uInt16 nWWVersion = pWwFib->nProduct & 0xE000;
+ switch ( nWWVersion )
+ {
+ case 0x0000: // version 8 aka Microsoft Word 97
+ {
+ bIsObjectLayoutInTableCell = false;
+ ASSERT( nLayoutInTableCell == 0xFFFFFFFF,
+ "no explicit object attribute layout in table cell excepted." );
+ }
+ break;
+ case 0x2000: // version 9 aka Microsoft Word 2000
+ case 0x4000: // version 10 aka Microsoft Word 2002
+ case 0x6000: // version 11 aka Microsoft Word 2003
+ case 0x8000: // version 12 aka Microsoft Word 2007
+ {
+ // --> OD 2009-01-13 #i98037#
+ // adjustment of conditions needed after deeper analysis of
+ // certain test cases.
+ if ( nLayoutInTableCell == 0xFFFFFFFF || // no explicit attribute value given
+ nLayoutInTableCell & 0x80008000 ||
+ ( nLayoutInTableCell & 0x02000000 &&
+ !(nLayoutInTableCell & 0x80000000 ) ) )
+ // <--
+ {
+ bIsObjectLayoutInTableCell = true;
+ }
+ else
+ {
+ bIsObjectLayoutInTableCell = false;
+ }
+ }
+ break;
+ default:
+ {
+ ASSERT( false,
+ "unknown version." );
+ }
+ }
+ }
+
+ return bIsObjectLayoutInTableCell;
+}
+// <--
+
+SwFrmFmt* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp )
+{
+ if( nIniFlags & WW8FL_NO_GRAFLAYER )
+ return 0;
+
+ ::SetProgressState(nProgress, mpDocShell); // Update
+
+ nDrawCpO = pWwFib->GetBaseCp(pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX);
+
+ GrafikCtor();
+
+ WW8PLCFspecial* pPF = pPlcxMan->GetFdoa();
+ if( !pPF )
+ {
+ ASSERT( !this, "Where is the grapic (1) ?" );
+ return 0;
+ }
+
+ if( bVer67 )
+ {
+ long nOldPos = pStrm->Tell();
+
+ nDrawXOfs = nDrawYOfs = 0;
+ ReadGrafLayer1( pPF, nGrafAnchorCp );
+
+ pStrm->Seek( nOldPos );
+ return 0;
+ }
+
+ //Normal case of Word 8+ version stuff
+ pPF->SeekPos( nGrafAnchorCp );
+
+ WW8_FC nStartFc;
+ void* pF0;
+ if( !pPF->Get( nStartFc, pF0 ) ){
+ ASSERT( !this, "+Wo ist die Grafik (2) ?" );
+ return 0;
+ }
+
+ WW8_FSPA_SHADOW* pFS = (WW8_FSPA_SHADOW*)pF0;
+ WW8_FSPA* pF;
+#ifdef __WW8_NEEDS_COPY
+ WW8_FSPA aFSFA;
+ pF = &aFSFA;
+ WW8FSPAShadowToReal( pFS, pF );
+#else
+ pF = (WW8_FSPA*)pFS;
+#endif // defined __WW8_NEEDS_COPY
+ if( !pF->nSpId )
+ {
+ ASSERT( !this, "+Wo ist die Grafik (3) ?" );
+ return 0;
+ }
+
+ if (!pMSDffManager->GetModel())
+ pMSDffManager->SetModel(pDrawModel, 1440);
+
+
+ Rectangle aRect(pF->nXaLeft, pF->nYaTop, pF->nXaRight, pF->nYaBottom);
+ SvxMSDffImportData aData( aRect );
+
+ /*
+ #i20540#
+ The SdrOle2Obj will try and manage any ole objects it finds, causing all
+ sorts of trouble later on
+ */
+ SwDocShell* pPersist = rDoc.GetDocShell();
+ rDoc.SetDocShell(0); //#i20540# Persist guard
+
+ SdrObject* pObject = 0;
+ bool bOk = (pMSDffManager->GetShape(pF->nSpId, pObject, aData) && pObject);
+
+ rDoc.SetDocShell(pPersist); //#i20540# Persist guard
+
+ if (!bOk)
+ {
+ ASSERT( !this, "Where is the Shape ?" );
+ return 0;
+ }
+
+ bool bDone = false;
+ SdrObject* pOurNewObject = 0;
+ bool bReplaceable = false;
+
+ switch (SdrObjKind(pObject->GetObjIdentifier()))
+ {
+ case OBJ_GRAF:
+ bReplaceable = true;
+ bDone = true;
+ break;
+ case OBJ_OLE2:
+ bReplaceable = true;
+ break;
+ default:
+ break;
+
+ }
+
+ // OD 14.10.2003 - keep wrapping of objects in page header/footer.
+ /*
+ //#108778# when in a header or footer word appears to treat all elements
+ //are wrap through
+ if (bIsHeader || bIsFooter)
+ pF->nwr = 3;
+ */
+
+ // Umfluss-Modus ermitteln
+ SfxItemSet aFlySet(rDoc.GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1);
+ SwSurround eSurround = SURROUND_PARALLEL;
+ bool bContour = false;
+ switch (pF->nwr)
+ {
+ case 0: //0 like 2, but doesn't require absolute object
+ case 2: //2 wrap around absolute object
+ eSurround = SURROUND_PARALLEL;
+ break;
+ case 1: //1 no text next to shape
+ eSurround = SURROUND_NONE;
+ break;
+ case 3: //3 wrap as if no object present
+ eSurround = SURROUND_THROUGHT;
+ break;
+ case 4: //4 wrap tightly around object
+ case 5: //5 wrap tightly, but allow holes
+ eSurround = SURROUND_PARALLEL;
+ bContour = true;
+ break;
+ }
+
+ // bei Modus 2 oder 4 auch den Zusatzparameter beruecksichtigen
+ if ( (2 == pF->nwr) || (4 == pF->nwr) )
+ {
+ switch( pF->nwrk )
+ {
+ //0 wrap both sides
+ case 0:
+ eSurround = SURROUND_PARALLEL;
+ break;
+ //1 wrap only on left
+ case 1:
+ eSurround = SURROUND_LEFT;
+ break;
+ //2 wrap only on right
+ case 2:
+ eSurround = SURROUND_RIGHT;
+ break;
+ //3 wrap only on largest side
+ case 3:
+ eSurround = SURROUND_IDEAL;
+ break;
+ }
+ }
+
+ SwFmtSurround aSur( eSurround );
+ aSur.SetContour( bContour );
+ aSur.SetOutside(true); // Winword kann nur Aussen-Konturen
+ aFlySet.Put( aSur );
+
+ // eingelesenes Objekt (kann eine ganze Gruppe sein) jetzt korrekt
+ // positionieren usw.
+
+ ASSERT(!((aData.GetRecCount() != 1) && bReplaceable),
+ "Replaceable drawing with > 1 entries ?");
+
+ if (aData.GetRecCount() != 1)
+ bReplaceable = false;
+
+ SvxMSDffImportRec* pRecord = 0;
+ /*
+ Get the record for top level object, so we can get the word anchoring
+ and wrapping information for it.
+ */
+ sal_uInt16 nRecCount = aData.GetRecCount();
+ for (sal_uInt16 nTxbx=0; nTxbx < nRecCount; ++nTxbx )
+ {
+ pRecord = aData.GetRecord( nTxbx );
+ if (pRecord && pRecord->pObj == pObject)
+ break;
+ else
+ pRecord = 0;
+ }
+
+ ASSERT(pRecord, "how did that happen?");
+ if (!pRecord)
+ return 0;
+
+ // --> OD 2008-04-10 #i84783#
+// //cmc: We're in a table, and the element has the magic Word XP bit set
+// //to enable layout inside a cell
+// // --> OD 2005-08-10 #124714# - undo change made for issue #i33442#
+// bool bLayoutInTableCell = ( nInTable &&
+// pRecord->nLayoutInTableCell & 0x00008000 );
+// // <--
+ const bool bLayoutInTableCell =
+ nInTable && IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell );
+ // <--
+
+ // OD 14.10.2003 #i18732#
+ // Switch on 'follow text flow',
+ // if object is laid out inside table cell and
+ // its wrapping isn't 'SURROUND_THROUGH'
+ if (bLayoutInTableCell && eSurround != SURROUND_THROUGHT)
+ {
+ SwFmtFollowTextFlow aFollowTextFlow( sal_True );
+ aFlySet.Put( aFollowTextFlow );
+ }
+
+
+ //#i21847#
+ //Some shapes are set to *hidden*, don't import those ones.
+ if (pRecord->bHidden)
+ return 0;
+
+ // If we are to be "below text" then we are not to be opaque
+ // #i14045# MM If we are in a header or footer then make the object transparent
+ // Not exactly like word but close enough for now
+
+ // --> OD 2005-03-07 #b6234902# - both flags <bBelowText> and <bDrawHell>
+ // have to be set to move object into the background.
+ // --> OD 2005-04-11 #i46794# - it reveals that value of flag <bBelowText>
+ // can be neglected.
+ const bool bMoveToBackgrd = pRecord->bDrawHell ||
+ ( ( bIsHeader || bIsFooter ) && pF->nwr == 3 );
+ if ( bMoveToBackgrd )
+ aFlySet.Put(SvxOpaqueItem(RES_OPAQUE,false));
+
+ String aObjName = pObject->GetName();
+
+ SwFrmFmt* pRetFrmFmt = 0;
+ if (bReplaceable)
+ {
+ //Single graphics or ole objects
+ pRetFrmFmt = ImportReplaceableDrawables(pObject, pOurNewObject, pRecord,
+ pF, aFlySet);
+ }
+ else
+ {
+ //Drawing objects, (e.g. ovals or drawing groups)
+ if (pF->bRcaSimple)
+ {
+ pF->nbx = WW8_FSPA::RelPageBorder;
+ pF->nby = WW8_FSPA::RelPageBorder;
+ }
+
+ RndStdIds eAnchor = ProcessEscherAlign(pRecord, pF, aFlySet,
+ bReplaceable);
+
+ // Should we, and is it possible to make this into a writer textbox
+ if ((!(nIniFlags1 & WW8FL_NO_FLY_FOR_TXBX)) && pRecord->bReplaceByFly)
+ {
+ pRetFrmFmt = ConvertDrawTextToFly(pObject, pOurNewObject, pRecord,
+ eAnchor, pF, aFlySet);
+ if (pRetFrmFmt)
+ bDone = true;
+ }
+
+ if (!bDone)
+ {
+ sw::util::SetLayer aSetLayer(rDoc);
+ if ( bMoveToBackgrd )
+ aSetLayer.SendObjectToHell(*pObject);
+ else
+ aSetLayer.SendObjectToHeaven(*pObject);
+
+ if (!IsInlineEscherHack())
+ {
+ /*
+ #97824# Need to make sure that the correct layer ordering is
+ applied.
+ */
+ // --> OD 2004-12-13 #117915# - pass information, if object
+ // is in page header|footer to method.
+ pWWZOrder->InsertEscherObject( pObject, pF->nSpId,
+ bIsHeader || bIsFooter );
+ // <--
+ }
+ else
+ {
+ pWWZOrder->InsertTextLayerObject(pObject);
+ }
+
+ pRetFrmFmt = rDoc.Insert(*pPaM, *pObject, &aFlySet, NULL);
+
+ ASSERT(pRetFrmFmt->GetAnchor().GetAnchorId() ==
+ eAnchor, "Not the anchor type requested!");
+
+ /*
+ Insert text if necessary into textboxes contained in groups.
+ */
+ if (aData.HasRecords())
+ {
+ sal_uInt16 nCount = aData.GetRecCount();
+ for (sal_uInt16 nTxbx=0; nTxbx < nCount; ++nTxbx)
+ {
+ pRecord = aData.GetRecord(nTxbx);
+ if (pRecord && pRecord->pObj && pRecord->aTextId.nTxBxS)
+ { // #i52825# pRetFrmFmt can be NULL
+ pRetFrmFmt = MungeTextIntoDrawBox(pRecord->pObj,
+ pRecord, nGrafAnchorCp, pRetFrmFmt);
+ }
+ }
+ }
+ }
+ }
+
+ // --> OD 2005-03-11 #i44344#, #i44681# - positioning attributes already set
+ if ( pRetFrmFmt /*#i52825# */ && pRetFrmFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(pRetFrmFmt)->PosAttrSet();
+ }
+ // <--
+ if (!IsInlineEscherHack())
+ MapWrapIntoFlyFmt(pRecord, pRetFrmFmt);
+
+ // Set frame name with object name
+ if( aObjName.Len() )
+ pRetFrmFmt->SetName( aObjName );
+ return AddAutoAnchor(pRetFrmFmt);
+}
+
+SwFrmFmt *SwWW8ImplReader::AddAutoAnchor(SwFrmFmt *pFmt)
+{
+ if (pFmt && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR))
+ {
+ sal_uInt16 nTextAreaWidth = static_cast< sal_uInt16 >( maSectionManager.GetPageWidth() -
+ maSectionManager.GetPageRight() - maSectionManager.GetPageLeft());
+
+ if (pFmt->GetFrmSize().GetSize().Width() > nTextAreaWidth)
+ maTracer.Log(sw::log::eTooWideAsChar);
+ }
+
+ /*
+ * anchored to character at the current position will move along the
+ * paragraph as text is added because we are at the insertion point.
+ *
+ * Leave to later and set the correct location then.
+ */
+ if ((pFmt) && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR))
+ {
+ pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFmt);
+ }
+ return pFmt;
+}
+
+SwFrmFmt* SwWW8ImplReader::MungeTextIntoDrawBox(SdrObject* pTrueObject,
+ SvxMSDffImportRec *pRecord, long nGrafAnchorCp, SwFrmFmt* pRetFrmFmt)
+{
+ SdrTextObj* pSdrTextObj;
+
+ // Pruefen, ob Gruppenobjekt (z.B. zwei Klammern) vorliegt
+ if (SdrObjGroup* pThisGroup = PTR_CAST(SdrObjGroup, pRecord->pObj))
+ {
+ // Gruppenobjekte haben keinen Text. Fuege ein Textobjekt in die
+ // Gruppe ein, um den Text zu halten.
+ pSdrTextObj = new SdrRectObj( OBJ_TEXT, pThisGroup->GetCurrentBoundRect());
+
+ SfxItemSet aSet(pDrawModel->GetItemPool());
+ aSet.Put(XFillStyleItem(XFILL_NONE));
+ aSet.Put(XLineStyleItem(XLINE_NONE));
+ aSet.Put(SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE ));
+ aSet.Put(SdrTextAutoGrowHeightItem(false));
+ aSet.Put(SdrTextAutoGrowWidthItem(false));
+ pSdrTextObj->SetMergedItemSet(aSet);
+
+ long nAngle = pRecord->nTextRotationAngle;
+ if ( nAngle )
+ {
+ double a = nAngle*nPi180;
+ pSdrTextObj->NbcRotate(pSdrTextObj->GetCurrentBoundRect().Center(), nAngle,
+ sin(a), cos(a) );
+ }
+
+ pSdrTextObj->NbcSetLayer( pThisGroup->GetLayer() );
+ pThisGroup->GetSubList()->NbcInsertObject(pSdrTextObj);
+ }
+ else
+ pSdrTextObj = PTR_CAST(SdrTextObj, pRecord->pObj);
+
+ if( pSdrTextObj )
+ {
+ Size aObjSize(pSdrTextObj->GetSnapRect().GetWidth(),
+ pSdrTextObj->GetSnapRect().GetHeight());
+
+ // Objekt ist Bestandteil einer Gruppe?
+ SdrObject* pGroupObject = pSdrTextObj->GetUpGroup();
+
+ sal_uInt32 nOrdNum = pSdrTextObj->GetOrdNum();
+ bool bEraseThisObject;
+ InsertTxbxText( pSdrTextObj, &aObjSize, pRecord->aTextId.nTxBxS,
+ pRecord->aTextId.nSequence, nGrafAnchorCp, pRetFrmFmt,
+ (pSdrTextObj != pTrueObject) || (0 != pGroupObject),
+ bEraseThisObject, 0, 0, 0, 0, pRecord);
+
+ // wurde dieses Objekt ersetzt ??
+ if (bEraseThisObject)
+ {
+ if( pGroupObject || (pSdrTextObj != pTrueObject) )
+ {
+ // Objekt wurde bereits (in der Gruppe und) der Drawing-Page
+ // durch ein neues SdrGrafObj ersetzt.
+
+ SdrObject* pNewObj = pGroupObject ?
+ pGroupObject->GetSubList()->GetObj(nOrdNum) : pTrueObject;
+ if (pSdrTextObj != pNewObj)
+ {
+ // Objekt in der Z-Order-Liste ersetzen
+ pMSDffManager->ExchangeInShapeOrder(pSdrTextObj, 0,0, pNewObj);
+ // Objekt jetzt noch loeschen
+ SdrObject::Free( pRecord->pObj );
+ // und das neue Objekt merken.
+ pRecord->pObj = pNewObj;
+ }
+ }
+ else
+ {
+ // Objekt aus der Z-Order-Liste loeschen
+ pMSDffManager->RemoveFromShapeOrder( pSdrTextObj );
+ // Objekt aus der Drawing-Page rausnehmen
+ if( pSdrTextObj->GetPage() )
+ pDrawPg->RemoveObject( pSdrTextObj->GetOrdNum() );
+ // und FrameFormat entfernen, da durch Grafik ersetzt (dies
+ // loescht auch das Objekt)
+ rDoc.DelFrmFmt( pRetFrmFmt );
+ pRetFrmFmt = 0;
+ // auch den Objektmerker loeschen
+ pRecord->pObj = 0;
+ }
+ }
+ else
+ {
+ // ww8-default Randabstand einsetzen
+ SfxItemSet aItemSet(pDrawModel->GetItemPool(),
+ SDRATTR_TEXT_LEFTDIST, SDRATTR_TEXT_LOWERDIST);
+ aItemSet.Put( SdrTextLeftDistItem( pRecord->nDxTextLeft ) );
+ aItemSet.Put( SdrTextRightDistItem( pRecord->nDxTextRight ) );
+ aItemSet.Put( SdrTextUpperDistItem( pRecord->nDyTextTop ) );
+ aItemSet.Put( SdrTextLowerDistItem( pRecord->nDyTextBottom ) );
+ pSdrTextObj->SetMergedItemSetAndBroadcast(aItemSet);
+ }
+ }
+ return pRetFrmFmt;
+}
+
+SwFlyFrmFmt* SwWW8ImplReader::ConvertDrawTextToFly(SdrObject* &rpObject,
+ SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, RndStdIds eAnchor,
+ WW8_FSPA *pF, SfxItemSet &rFlySet)
+{
+ SwFlyFrmFmt* pRetFrmFmt = 0;
+ long nStartCp;
+ long nEndCp;
+
+ // Pruefen, ob in dieser Textbox-Kette denn Text enthalten ist. (
+ // Umwandeln einer leeren Kette in Rahmen waere Unsinn. )
+ if ( TxbxChainContainsRealText(pRecord->aTextId.nTxBxS,nStartCp,nEndCp) )
+ {
+ // Der Text wird nicht in das SdrTextObj eingelesen! Stattdessen wird
+ // ein Rahmen eingefuegt und der Text von nStartCp bis nEndCp dort
+ // hinein gelesen.
+ //
+ // Vorteil: im Rahmen sind viel mehr Attribute moeglich als in der
+ // Edit-Enging, und es koennen auch Felder, OLEs oder Grafiken darin
+ // sein...
+
+ Rectangle aInnerDist(pRecord->nDxTextLeft, pRecord->nDyTextTop,
+ pRecord->nDxTextRight, pRecord->nDyTextBottom);
+
+ SwFmtFrmSize aFrmSize(ATT_FIX_SIZE, pF->nXaRight - pF->nXaLeft, pF->nYaBottom - pF->nYaTop);
+ aFrmSize.SetWidthSizeType(pRecord->bAutoWidth ? ATT_VAR_SIZE : ATT_FIX_SIZE);
+ rFlySet.Put(aFrmSize);
+
+ MatchSdrItemsIntoFlySet( rpObject, rFlySet, pRecord->eLineStyle,
+ pRecord->eShapeType, aInnerDist );
+
+
+ SdrTextObj *pSdrTextObj = PTR_CAST(SdrTextObj, rpObject);
+ if (pSdrTextObj && pSdrTextObj->IsVerticalWriting())
+ rFlySet.Put(SvxFrameDirectionItem(FRMDIR_VERT_TOP_RIGHT, RES_FRAMEDIR));
+
+ pRetFrmFmt = rDoc.MakeFlySection(eAnchor, pPaM->GetPoint(), &rFlySet);
+ ASSERT(pRetFrmFmt->GetAnchor().GetAnchorId() == eAnchor,
+ "Not the anchor type requested!");
+
+ // falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste
+ // entsprechend korrigieren (oder Eintrag loeschen)
+ rpOurNewObject = CreateContactObject(pRetFrmFmt);
+
+ // altes Objekt aus der Z-Order-Liste entfernen
+ pMSDffManager->RemoveFromShapeOrder( rpObject );
+
+ // und das Objekt loeschen
+ SdrObject::Free( rpObject );
+ /*
+ Achtung: ab jetzt nur noch pOrgShapeObject
+ abfragen!
+ */
+
+ if (rpOurNewObject)
+ {
+ /*
+ #96375#
+ We do not store our rpOutNewObject in the ShapeOrder because we
+ have a FrmFmt from which we can regenerate the contact object when
+ we need it. Because, we can have frames anchored to paragraphs in
+ header/footers and we can copy header/footers, if we do copy a
+ header/footer with a nonpage anchored frame in it then the contact
+ objects are invalidated. Under this condition the FrmFmt will be
+ updated to reflect this change and can be used to get a new
+ contact object, while a raw rpOutNewObject stored here becomes
+ deleted and useless.
+ */
+ pMSDffManager->StoreShapeOrder(pF->nSpId,
+ (((sal_uLong)pRecord->aTextId.nTxBxS) << 16) +
+ pRecord->aTextId.nSequence, 0, pRetFrmFmt);
+
+ // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit
+ // in SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden
+ // kann !!!
+ if (!rpOurNewObject->IsInserted())
+ {
+ // --> OD 2004-12-13 #117915# - pass information, if object
+ // is in page header|footer to method.
+ pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
+ bIsHeader || bIsFooter );
+ // <--
+ }
+ }
+
+ // Box-0 erhaelt den Text fuer die ganze Kette!
+ if( !pRecord->aTextId.nSequence )
+ {
+ // rette Flags u.ae. und setze sie zurueck
+ WW8ReaderSave aSave( this );
+
+ MoveInsideFly(pRetFrmFmt);
+
+ SwNodeIndex aStart(pPaM->GetPoint()->nNode);
+
+ pWWZOrder->InsideEscher(pF->nSpId);
+
+ // lies den Text ein
+ bTxbxFlySection = true;
+ bool bJoined = ReadText(nStartCp, (nEndCp-nStartCp),
+ MAN_MAINTEXT == pPlcxMan->GetManType() ?
+ MAN_TXBX : MAN_TXBX_HDFT);
+
+ pWWZOrder->OutsideEscher();
+
+ MoveOutsideFly(pRetFrmFmt, aSave.GetStartPos(),!bJoined);
+
+ aSave.Restore( this );
+ }
+ }
+ return pRetFrmFmt;
+}
+
+void MatchEscherMirrorIntoFlySet(const SvxMSDffImportRec &rRecord,
+ SfxItemSet &rFlySet)
+{
+ if (rRecord.bVFlip || rRecord.bHFlip)
+ {
+ MirrorGraph eType(RES_MIRROR_GRAPH_DONT);
+ if (rRecord.bVFlip && rRecord.bHFlip)
+ eType = RES_MIRROR_GRAPH_BOTH;
+ else if (rRecord.bVFlip)
+ eType = RES_MIRROR_GRAPH_HOR;
+ else
+ eType = RES_MIRROR_GRAPH_VERT;
+ rFlySet.Put( SwMirrorGrf(eType) );
+ }
+}
+
+SwFlyFrmFmt* SwWW8ImplReader::ImportReplaceableDrawables( SdrObject* &rpObject,
+ SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, WW8_FSPA *pF,
+ SfxItemSet &rFlySet )
+{
+ SwFlyFrmFmt* pRetFrmFmt = 0;
+ long nWidthTw = pF->nXaRight - pF->nXaLeft;
+ if (0 > nWidthTw)
+ nWidthTw = 0;
+ long nHeightTw = pF->nYaBottom - pF->nYaTop;
+ if (0 > nHeightTw)
+ nHeightTw = 0;
+
+ ProcessEscherAlign(pRecord, pF, rFlySet, true);
+
+ rFlySet.Put(SwFmtFrmSize(ATT_FIX_SIZE, nWidthTw, nHeightTw));
+
+ SfxItemSet aGrSet(rDoc.GetAttrPool(), RES_GRFATR_BEGIN, RES_GRFATR_END-1);
+
+ if (pRecord)
+ {
+ //Note that the escher inner distance only seems to be honoured in
+ //word for textboxes, not for graphics and ole objects.
+ Rectangle aInnerDist(0, 0, 0, 0);
+
+ MatchSdrItemsIntoFlySet(rpObject, rFlySet, pRecord->eLineStyle,
+ pRecord->eShapeType, aInnerDist);
+
+ MatchEscherMirrorIntoFlySet(*pRecord, aGrSet);
+ }
+
+ String aObjectName(rpObject->GetName());
+ if (OBJ_OLE2 == SdrObjKind(rpObject->GetObjIdentifier()))
+ pRetFrmFmt = InsertOle(*((SdrOle2Obj*)rpObject), rFlySet, aGrSet);
+ else
+ {
+ const SdrGrafObj *pGrf= (const SdrGrafObj*)rpObject;
+ bool bDone = false;
+ if (pGrf->IsLinkedGraphic() && pGrf->GetFileName().Len())
+ {
+ GraphicType eType = pGrf->GetGraphicType();
+ String aGrfName(
+ URIHelper::SmartRel2Abs(
+ INetURLObject(sBaseURL), pGrf->GetFileName(),
+ URIHelper::GetMaybeFileHdl()));
+ // --> OD 2005-07-04 #124117# - correction of fix for issue #i10939#:
+ // One of the two conditions have to be true to insert the graphic
+ // as a linked graphic -
+ if (GRAPHIC_NONE == eType || CanUseRemoteLink(aGrfName))
+ // <--
+ {
+ pRetFrmFmt = rDoc.Insert(*pPaM, aGrfName, aEmptyStr, 0,
+ &rFlySet, &aGrSet, NULL);
+ bDone = true;
+ }
+ }
+ if (!bDone)
+ {
+ const Graphic& rGraph = pGrf->GetGraphic();
+ pRetFrmFmt = rDoc.Insert(*pPaM, aEmptyStr, aEmptyStr, &rGraph,
+ &rFlySet, &aGrSet, NULL);
+ }
+ }
+
+ if (pRetFrmFmt)
+ {
+ if( pRecord )
+ {
+ if( OBJ_OLE2 != SdrObjKind(rpObject->GetObjIdentifier()) )
+ SetAttributesAtGrfNode( pRecord, pRetFrmFmt, pF );
+ }
+ // mehrfaches Auftreten gleicher Grafik-Namen vermeiden
+ maGrfNameGenerator.SetUniqueGraphName(pRetFrmFmt, aObjectName);
+ }
+ //falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste
+ //entsprechend korrigieren (oder Eintrag loeschen)
+ rpOurNewObject = CreateContactObject(pRetFrmFmt);
+
+ // altes Objekt aus der Z-Order-Liste entfernen
+ pMSDffManager->RemoveFromShapeOrder( rpObject );
+ // aus der Drawing-Page rausnehmen
+ if( rpObject->GetPage() )
+ pDrawPg->RemoveObject( rpObject->GetOrdNum() );
+
+ // und das Objekt loeschen
+ SdrObject::Free( rpObject );
+ /*
+ Achtung: ab jetzt nur noch pOrgShapeObject abfragen!
+ */
+
+ // Kontakt-Objekt in die Z-Order-Liste und die Page aufnehmen
+ if (rpOurNewObject)
+ {
+ if (!bHdFtFtnEdn)
+ pMSDffManager->StoreShapeOrder(pF->nSpId, 0, rpOurNewObject, 0 );
+
+ // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit in
+ // SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden kann !!!
+ if (!rpOurNewObject->IsInserted())
+ {
+ // --> OD 2004-12-13 #117915# - pass information, if object
+ // is in page header|footer to method.
+ pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
+ bIsHeader || bIsFooter );
+ // <--
+ }
+ }
+ return pRetFrmFmt;
+}
+
+void SwWW8ImplReader::GrafikCtor() // Fuer SVDraw und VCControls und Escher
+{
+ if (!pDrawModel)
+ {
+ // --> OD 2005-08-08 #i52858# - method name changed
+ rDoc.GetOrCreateDrawModel();
+ // <--
+ pDrawModel = rDoc.GetDrawModel();
+ ASSERT(pDrawModel, "Kann DrawModel nicht anlegen");
+ pDrawPg = pDrawModel->GetPage(0);
+
+ pMSDffManager = new SwMSDffManager(*this);
+ pMSDffManager->SetModel(pDrawModel, 1440);
+ /*
+ #79055#
+ Now the dff manager always needs a controls //converter as well, but a
+ control converter may still exist //without a dffmanager. cmc
+ */
+ pFormImpl = new SwMSConvertControls(mpDocShell, pPaM);
+
+ pWWZOrder = new wwZOrderer(sw::util::SetLayer(rDoc), pDrawPg,
+ pMSDffManager ? pMSDffManager->GetShapeOrders() : 0);
+ }
+}
+
+void SwWW8ImplReader::GrafikDtor()
+{
+ DELETEZ(mpDrawEditEngine); // evtl. von Grafik angelegt
+ DELETEZ(pWWZOrder); // dito
+}
+
+void SwWW8FltAnchorStack::AddAnchor(const SwPosition& rPos, SwFrmFmt *pFmt)
+{
+ ASSERT(pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR,
+ "Don't use fltanchors with inline frames, slap!");
+ NewAttr(rPos, SwFltAnchor(pFmt));
+}
+
+void SwWW8FltAnchorStack::Flush()
+{
+ sal_uInt16 nCnt = static_cast< sal_uInt16 >(Count());
+ for (sal_uInt16 i=0; i < nCnt; ++i)
+ {
+ SwFltStackEntry *pEntry = (*this)[i];
+ SwPosition aDummy(pEntry->nMkNode);
+ SetAttrInDoc(aDummy,pEntry);
+ DeleteAndDestroy(i--);
+ --nCnt;
+ }
+}
+
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */