1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ 31 #include <svl/urihelper.hxx> 32 #include <hintids.hxx> 33 #include <osl/endian.h> 34 #include <svx/fmglob.hxx> 35 #include <svx/sdtaitm.hxx> 36 #include <editeng/lrspitem.hxx> 37 #include <editeng/udlnitem.hxx> 38 #include <svx/xlineit.hxx> 39 #include <svx/xfillit.hxx> 40 #include <svx/svdmodel.hxx> 41 #include <svx/sdtaitm.hxx> 42 #include <svx/svdocapt.hxx> 43 #include <svx/sxctitm.hxx> 44 #include <editeng/editeng.hxx> 45 #include <svx/svdpage.hxx> 46 #include <svx/svdopath.hxx> 47 #include <svx/svdocirc.hxx> 48 #include <editeng/outlobj.hxx> 49 #include <svx/svdogrp.hxx> 50 #include <svx/svdograf.hxx> 51 #include <svx/svdoole2.hxx> 52 #include <editeng/colritem.hxx> 53 #include <editeng/fhgtitem.hxx> 54 #include <editeng/postitem.hxx> 55 #include <editeng/adjitem.hxx> 56 #include <editeng/wghtitem.hxx> 57 #include <editeng/crsditem.hxx> 58 #include <editeng/cntritem.hxx> 59 #include <editeng/shdditem.hxx> 60 #include <editeng/fontitem.hxx> 61 #include <editeng/ulspitem.hxx> 62 #include <svx/svdoattr.hxx> 63 #include <editeng/brshitem.hxx> 64 #include <svx/rectenum.hxx> 65 #include <editeng/opaqitem.hxx> 66 #include <editeng/shaditem.hxx> 67 #include <editeng/shaditem.hxx> 68 #include <editeng/boxitem.hxx> 69 #include <editeng/outliner.hxx> // #79453# 70 #include <editeng/frmdiritem.hxx> 71 #include <svx/xfltrit.hxx> 72 #include <filter/msfilter/msdffimp.hxx> 73 #include <grfatr.hxx> // class SwCropGrf 74 #include <fmtornt.hxx> 75 #include <fmtcntnt.hxx> 76 #include <frmfmt.hxx> 77 #include <fmtanchr.hxx> 78 #include <pam.hxx> 79 #include <doc.hxx> 80 #include <docary.hxx> 81 #include <ndgrf.hxx> 82 #include <ndtxt.hxx> 83 #include <dcontact.hxx> 84 #include <docsh.hxx> 85 #include <mdiexp.hxx> // Progress 86 #include <fmtcnct.hxx> 87 #include <swunodef.hxx> 88 #include "ww8struc.hxx" 89 #include "ww8scan.hxx" 90 #include "ww8par.hxx" // class SwWWImplReader 91 #include "ww8par2.hxx" // SwWW8StyInf 92 #include "ww8graf.hxx" 93 #include <fmtinfmt.hxx> 94 #include <editeng/eeitem.hxx> 95 #include <editeng/flditem.hxx> 96 // OD 30.09.2003 #i18732# 97 #include <fmtfollowtextflow.hxx> 98 #include "writerhelper.hxx" 99 #include "writerwordglue.hxx" 100 #include <basegfx/point/b2dpoint.hxx> 101 #include <basegfx/polygon/b2dpolygon.hxx> 102 #include <editeng/editobj.hxx> 103 104 #include <math.h> 105 106 using namespace ::com::sun::star; 107 using namespace sw::types; 108 using namespace sw::util; 109 110 // Hilfsroutinen 111 112 Color WW8TransCol(SVBT32 nWC) 113 { 114 #if 1 // 1 = Vordefinierte Farben benutzen, 0 = ignorieren 115 116 // Farbtabelle zum Umrechnen RGB-Werte in vordefinierte Farben 117 // ( Damit bei der Writer-UI die Farbnamen stimmen ) 118 // Die Tabelle int im *3er-System* aufgeteilt. Die Grauwerte fehlen, 119 // da sie nicht ins 3er-System passen ( 4 Werte: sw, ws, 2 * grau ) 120 static ColorData eColA[] = { // B G R B G R B G R 121 COL_BLACK, COL_RED, COL_LIGHTRED, // 0 0 0, 0 0 1, 0 0 2 122 COL_GREEN, COL_BROWN, COL_BLACK, // 0 1 0, 0 1 1, 0 1 2 123 COL_LIGHTGREEN, COL_BLACK, COL_YELLOW, // 0 2 0, 0 2 1, 0 2 2 124 COL_BLUE, COL_MAGENTA, COL_BLACK, // 1 0 0, 1 0 1, 1 0 2 125 COL_CYAN, COL_LIGHTGRAY, COL_BLACK, // 1 1 0, 1 1 1, 1 1 2 126 COL_BLACK, COL_BLACK, COL_BLACK, // 1 2 0, 1 2 1, 1 2 2 127 COL_LIGHTBLUE, COL_BLACK, COL_LIGHTMAGENTA, // 2 0 0, 2 0 1, 2 0 2 128 COL_BLACK, COL_BLACK, COL_BLACK, // 2 1 0, 2 1 1, 2 1 2 129 COL_LIGHTCYAN, COL_BLACK, COL_WHITE }; // 2 2 0, 2 2 1, 2 2 2 130 131 // In nWC[3] steht ein Byte, dass in der WW-Doku nicht beschrieben ist. 132 // Die Bedeutung ist anscheinend folgende: Bei 0 ist es eine normale 133 // Farbe, dessen RGB-Wert in nWC[0..2] steht. stehen in nWC[3] die 134 // Werte 0x1, 0x7d oder 0x83, dann ist es ein Grauwert, dessen 135 // Schwarzanteil in 1/2 % in nWC[0] steht. 136 // Ich vermute, dass es auf Bit0 in nWV[3] ankommt, ob es RGB oder Grau ist. 137 138 if( !( nWC[3] & 0x1 ) && // keine Spezial-Farbe (grau) 139 ( ( nWC[0] == 0 || nWC[0]== 0x80 || nWC[0] == 0xff ) // R-Anteil 140 && ( nWC[1] == 0 || nWC[1]== 0x80 || nWC[1] == 0xff ) // G-Anteil 141 && ( nWC[2] == 0 || nWC[2]== 0x80 || nWC[2] == 0xff ) ) ){// B-Anteil 142 int nIdx = 0; // und nun: Idx-Berechnung im 3er-System 143 for (int i = 2; i >= 0; i--) 144 { 145 nIdx *= 3; 146 if (nWC[i]) 147 nIdx += ((nWC[i] == 0xff) ? 2 : 1); 148 } 149 if (eColA[nIdx] != COL_BLACK) 150 return Color(eColA[nIdx]); // Standard-Color 151 } 152 #endif 153 154 if (nWC[3] & 0x1) 155 { 156 //Special colour gray 157 sal_uInt8 u = (sal_uInt8)( (sal_uLong)( 200 - nWC[0] ) * 256 / 200 ); 158 return Color(u, u, u); 159 } 160 161 // User-Color 162 return Color(nWC[0], nWC[1], nWC[2]); 163 } 164 165 void wwFrameNamer::SetUniqueGraphName(SwFrmFmt *pFrmFmt, const String &rFixed) 166 { 167 if (mbIsDisabled || !rFixed.Len()) 168 return; 169 String aName(msSeed); 170 aName += String::CreateFromInt32(++mnImportedGraphicsCount); 171 aName.APPEND_CONST_ASC( ": " ); 172 aName += rFixed; 173 pFrmFmt->SetName( aName ); 174 } 175 176 // ReadGrafStart liest die ObjektDaten ein und erzeugt falls noetig einen Anker 177 bool SwWW8ImplReader::ReadGrafStart(void* pData, short nDataSiz, 178 WW8_DPHEAD* pHd, const WW8_DO* pDo, SfxAllItemSet &rSet) 179 { 180 if (SVBT16ToShort(pHd->cb) < sizeof(WW8_DPHEAD) + nDataSiz) 181 { 182 ASSERT( !this, "+Grafik-Element: Size ?" ); 183 pStrm->SeekRel(SVBT16ToShort(pHd->cb) - sizeof(WW8_DPHEAD)); 184 return false; 185 } 186 pStrm->Read(pData, nDataSiz); 187 188 RndStdIds eAnchor = (SVBT8ToByte(pDo->by) < 2) ? FLY_AT_PAGE : FLY_AT_PARA; 189 rSet.Put(SwFmtAnchor(eAnchor)); 190 191 nDrawXOfs2 = nDrawXOfs; 192 nDrawYOfs2 = nDrawYOfs; 193 194 if (eAnchor == FLY_AT_PARA) 195 { 196 if( SVBT8ToByte( pDo->bx ) == 1 ) // Pos: echt links 197 nDrawXOfs2 = static_cast< short >(nDrawXOfs2 - maSectionManager.GetPageLeft()); 198 if( nInTable ) // Obj in Table 199 nDrawXOfs2 = nDrawXOfs2 - GetTableLeft(); // -> siehe Kommentar 200 // bei GetTableLeft() 201 } 202 else 203 { 204 if( SVBT8ToByte( pDo->bx ) != 1 ) 205 nDrawXOfs2 = static_cast< short >(nDrawXOfs2 + maSectionManager.GetPageLeft()); 206 } 207 208 return true; 209 } 210 211 // SetStdAttr() setzt die Attribute, die jedes Objekt hat 212 213 static void SetStdAttr( SfxItemSet& rSet, WW8_DP_LINETYPE& rL, 214 WW8_DP_SHADOW& rSh ) 215 { 216 if( SVBT16ToShort( rL.lnps ) == 5 ){ // unsichtbar 217 rSet.Put( XLineStyleItem( XLINE_NONE ) ); 218 }else{ // sichtbar 219 Color aCol( WW8TransCol( rL.lnpc ) ); // LinienFarbe 220 rSet.Put( XLineColorItem( aEmptyStr, aCol ) ); 221 rSet.Put( XLineWidthItem( SVBT16ToShort( rL.lnpw ) ) ); 222 // LinienDicke 223 if( SVBT16ToShort( rL.lnps ) >= 1 224 && SVBT16ToShort(rL.lnps ) <= 4 ){ // LinienStil 225 rSet.Put( XLineStyleItem( XLINE_DASH ) ); 226 sal_Int16 nLen = SVBT16ToShort( rL.lnpw ); 227 XDash aD( XDASH_RECT, 1, 2 * nLen, 1, 5 * nLen, 5 * nLen ); 228 switch( SVBT16ToShort( rL.lnps ) ){ 229 case 1: aD.SetDots( 0 ); // Dash 230 aD.SetDashLen( 6 * nLen ); 231 aD.SetDistance( 4 * nLen ); 232 break; 233 case 2: aD.SetDashes( 0 ); break; // Dot 234 case 3: break; // Dash Dot 235 case 4: aD.SetDots( 2 ); break; // Dash Dot Dot 236 } 237 rSet.Put( XLineDashItem( aEmptyStr, aD ) ); 238 }else{ 239 rSet.Put( XLineStyleItem( XLINE_SOLID ) ); // noetig fuer TextBox 240 } 241 } 242 if( SVBT16ToShort( rSh.shdwpi ) ){ // Schatten 243 rSet.Put(SdrShadowItem(true)); 244 rSet.Put( SdrShadowXDistItem( SVBT16ToShort( rSh.xaOffset ) ) ); 245 rSet.Put( SdrShadowYDistItem( SVBT16ToShort( rSh.yaOffset ) ) ); 246 } 247 } 248 249 // SetFill setzt Fuellattribute wie Vordergrund- und Hintergrund-Farbe 250 // und Muster durch Reduktion auf eine Farbe. 251 // SetFill() setzt z.Zt kein Muster, da Sdr das nur sehr umstaendlich kann 252 // und die Sdr-Schraffur ( XDash ) noch nicht fertig ist. 253 // Statt dessen wird eine Mischfarbe gewaehlt, die auf den entsprechenden 254 // Farbton zwischen den Farben liegt. 255 256 static void SetFill( SfxItemSet& rSet, WW8_DP_FILL& rFill ) 257 { 258 static sal_uInt8 nPatA[] = 259 { 260 0, 0, 5, 10, 20, 25, 30, 40, 50, 60, 70, 75, 80, 261 90, 50, 50, 50, 50, 50, 50, 33, 33, 33, 33, 33, 33 262 }; 263 sal_uInt16 nPat = SVBT16ToShort(rFill.flpp); 264 265 if (nPat == 0) // transparent 266 rSet.Put(XFillStyleItem(XFILL_NONE)); 267 else 268 { 269 rSet.Put(XFillStyleItem(XFILL_SOLID)); // necessary for textbox 270 if (nPat <= 1 || nPat > sizeof(nPatA)) 271 { 272 // Solid Background or unknown 273 rSet.Put(XFillColorItem(aEmptyStr, WW8TransCol(rFill.dlpcBg))); 274 } 275 else 276 { // Brush -> Farbmischung 277 Color aB( WW8TransCol( rFill.dlpcBg ) ); 278 Color aF( WW8TransCol( rFill.dlpcFg ) ); 279 aB.SetRed( (sal_uInt8)( ( (sal_uLong)aF.GetRed() * nPatA[nPat] 280 + (sal_uLong)aB.GetRed() * ( 100 - nPatA[nPat] ) ) / 100 ) ); 281 aB.SetGreen( (sal_uInt8)( ( (sal_uLong)aF.GetGreen() * nPatA[nPat] 282 + (sal_uLong)aB.GetGreen() * ( 100 - nPatA[nPat] ) ) / 100 ) ); 283 aB.SetBlue( (sal_uInt8)( ( (sal_uLong)aF.GetBlue() * nPatA[nPat] 284 + (sal_uLong)aB.GetBlue() * ( 100 - nPatA[nPat] ) ) / 100 ) ); 285 rSet.Put( XFillColorItem( aEmptyStr, aB ) ); 286 } 287 } 288 } 289 290 static void SetLineEndAttr( SfxItemSet& rSet, WW8_DP_LINEEND& rLe, 291 WW8_DP_LINETYPE& rLt ) 292 { 293 sal_uInt16 aSB = SVBT16ToShort( rLe.aStartBits ); 294 if( aSB & 0x3 ) 295 { 296 ::basegfx::B2DPolygon aPolygon; 297 aPolygon.append(::basegfx::B2DPoint(0.0, 330.0)); 298 aPolygon.append(::basegfx::B2DPoint(100.0, 0.0)); 299 aPolygon.append(::basegfx::B2DPoint(200.0, 330.0)); 300 aPolygon.setClosed(true); 301 rSet.Put( XLineEndItem( aEmptyStr, ::basegfx::B2DPolyPolygon(aPolygon) ) ); 302 sal_uInt16 nSiz = SVBT16ToShort( rLt.lnpw ) 303 * ( ( aSB >> 2 & 0x3 ) + ( aSB >> 4 & 0x3 ) ); 304 if( nSiz < 220 ) nSiz = 220; 305 rSet.Put(XLineEndWidthItem(nSiz)); 306 rSet.Put(XLineEndCenterItem(false)); 307 } 308 309 sal_uInt16 aEB = SVBT16ToShort( rLe.aEndBits ); 310 if( aEB & 0x3 ){ 311 ::basegfx::B2DPolygon aPolygon; 312 aPolygon.append(::basegfx::B2DPoint(0.0, 330.0)); 313 aPolygon.append(::basegfx::B2DPoint(100.0, 0.0)); 314 aPolygon.append(::basegfx::B2DPoint(200.0, 330.0)); 315 aPolygon.setClosed(true); 316 rSet.Put( XLineStartItem( aEmptyStr, ::basegfx::B2DPolyPolygon(aPolygon) ) ); 317 sal_uInt16 nSiz = SVBT16ToShort( rLt.lnpw ) 318 * ( ( aEB >> 2 & 0x3 ) + ( aEB >> 4 & 0x3 ) ); 319 if( nSiz < 220 ) nSiz = 220; 320 rSet.Put(XLineStartWidthItem(nSiz)); 321 rSet.Put(XLineStartCenterItem(false)); 322 } 323 } 324 325 // Ab hier folgen die Routinen fuer die einzelnen Objekte 326 SdrObject* SwWW8ImplReader::ReadLine( WW8_DPHEAD* pHd, const WW8_DO* pDo, 327 SfxAllItemSet &rSet) 328 { 329 WW8_DP_LINE aLine; 330 331 if( !ReadGrafStart( (void*)&aLine, sizeof( aLine ), pHd, pDo, rSet ) ) 332 return 0; 333 334 Point aP[2]; 335 { 336 Point& rP0 = aP[0]; 337 Point& rP1 = aP[1]; 338 339 rP0.X() = (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2; 340 rP0.Y() = (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2; 341 rP1 = rP0; 342 rP0.X() += (sal_Int16)SVBT16ToShort( aLine.xaStart ); 343 rP0.Y() += (sal_Int16)SVBT16ToShort( aLine.yaStart ); 344 rP1.X() += (sal_Int16)SVBT16ToShort( aLine.xaEnd ); 345 rP1.Y() += (sal_Int16)SVBT16ToShort( aLine.yaEnd ); 346 } 347 348 ::basegfx::B2DPolygon aPolygon; 349 aPolygon.append(::basegfx::B2DPoint(aP[0].X(), aP[0].Y())); 350 aPolygon.append(::basegfx::B2DPoint(aP[1].X(), aP[1].Y())); 351 SdrObject* pObj = new SdrPathObj(OBJ_LINE, ::basegfx::B2DPolyPolygon(aPolygon)); 352 353 SetStdAttr( rSet, aLine.aLnt, aLine.aShd ); 354 SetLineEndAttr( rSet, aLine.aEpp, aLine.aLnt ); 355 356 return pObj; 357 } 358 359 SdrObject* SwWW8ImplReader::ReadRect( WW8_DPHEAD* pHd, const WW8_DO* pDo, 360 SfxAllItemSet &rSet) 361 { 362 WW8_DP_RECT aRect; 363 364 if( !ReadGrafStart( (void*)&aRect, sizeof( aRect ), pHd, pDo, rSet ) ) 365 return 0; 366 367 Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2, 368 (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 ); 369 Point aP1( aP0 ); 370 aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa ); 371 aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya ); 372 373 SdrObject* pObj = new SdrRectObj( Rectangle( aP0, aP1 ) ); 374 375 SetStdAttr( rSet, aRect.aLnt, aRect.aShd ); 376 SetFill( rSet, aRect.aFill ); 377 378 return pObj; 379 } 380 381 SdrObject* SwWW8ImplReader::ReadElipse( WW8_DPHEAD* pHd, const WW8_DO* pDo, 382 SfxAllItemSet &rSet) 383 { 384 WW8_DP_ELIPSE aElipse; 385 386 if( !ReadGrafStart( (void*)&aElipse, sizeof( aElipse ), pHd, pDo, rSet ) ) 387 return 0; 388 389 Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2, 390 (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 ); 391 Point aP1( aP0 ); 392 aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa ); 393 aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya ); 394 395 SdrObject* pObj = new SdrCircObj( OBJ_CIRC, Rectangle( aP0, aP1 ) ); 396 397 SetStdAttr( rSet, aElipse.aLnt, aElipse.aShd ); 398 SetFill( rSet, aElipse.aFill ); 399 400 return pObj; 401 } 402 403 SdrObject* SwWW8ImplReader::ReadArc( WW8_DPHEAD* pHd, const WW8_DO* pDo, 404 SfxAllItemSet &rSet) 405 { 406 WW8_DP_ARC aArc; 407 408 if( !ReadGrafStart( (void*)&aArc, sizeof( aArc ), pHd, pDo, rSet ) ) 409 return 0; 410 411 Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2, 412 (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 ); 413 Point aP1( aP0 ); 414 aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa ) * 2; 415 aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya ) * 2; 416 417 short nA[] = { 2, 3, 1, 0 }; 418 short nW = nA[ ( ( SVBT8ToByte( aArc.fLeft ) & 1 ) << 1 ) 419 + ( SVBT8ToByte( aArc.fUp ) & 1 ) ]; 420 if( !SVBT8ToByte( aArc.fLeft ) ){ 421 aP0.Y() -= (sal_Int16)SVBT16ToShort( pHd->dya ); 422 aP1.Y() -= (sal_Int16)SVBT16ToShort( pHd->dya ); 423 } 424 if( SVBT8ToByte( aArc.fUp ) ){ 425 aP0.X() -= (sal_Int16)SVBT16ToShort( pHd->dxa ); 426 aP1.X() -= (sal_Int16)SVBT16ToShort( pHd->dxa ); 427 } 428 429 SdrObject* pObj = new SdrCircObj( OBJ_SECT, Rectangle( aP0, aP1 ), 430 nW * 9000, ( ( nW + 1 ) & 3 ) * 9000 ); 431 432 SetStdAttr( rSet, aArc.aLnt, aArc.aShd ); 433 SetFill( rSet, aArc.aFill ); 434 435 return pObj; 436 } 437 438 SdrObject* SwWW8ImplReader::ReadPolyLine( WW8_DPHEAD* pHd, const WW8_DO* pDo, 439 SfxAllItemSet &rSet) 440 { 441 WW8_DP_POLYLINE aPoly; 442 443 if( !ReadGrafStart( (void*)&aPoly, sizeof( aPoly ), pHd, pDo, rSet ) ) 444 return 0; 445 446 sal_uInt16 nCount = SVBT16ToShort( aPoly.aBits1 ) >> 1 & 0x7fff; 447 SVBT16 *pP = new SVBT16[nCount * 2]; 448 pStrm->Read( pP, nCount * 4 ); // Punkte einlesen 449 Polygon aP( nCount ); 450 Point aPt; 451 sal_uInt16 i; 452 453 for( i=0; i<nCount; i++ ){ 454 aPt.X() = SVBT16ToShort( pP[i << 1] ) + nDrawXOfs2 455 + (sal_Int16)SVBT16ToShort( pHd->xa ); 456 aPt.Y() = SVBT16ToShort( pP[( i << 1 ) + 1] ) + nDrawYOfs2 457 + (sal_Int16)SVBT16ToShort( pHd->ya ); 458 aP[i] = aPt; 459 } 460 delete[] pP; 461 462 SdrObject* pObj = new SdrPathObj(( SVBT16ToShort( aPoly.aBits1 ) & 0x1 ) ? OBJ_POLY : OBJ_PLIN, ::basegfx::B2DPolyPolygon(aP.getB2DPolygon())); 463 SetStdAttr( rSet, aPoly.aLnt, aPoly.aShd ); 464 SetFill( rSet, aPoly.aFill ); 465 466 return pObj; 467 } 468 469 ESelection SwWW8ImplReader::GetESelection( long nCpStart, long nCpEnd ) 470 { 471 sal_uInt16 nPCnt = mpDrawEditEngine->GetParagraphCount(); 472 sal_uInt16 nSP = 0; 473 sal_uInt16 nEP = 0; 474 while( (nSP < nPCnt) 475 && (nCpStart >= mpDrawEditEngine->GetTextLen( nSP ) + 1) ) 476 { 477 nCpStart -= mpDrawEditEngine->GetTextLen( nSP ) + 1; 478 nSP++; 479 } 480 // Beim Ende erst 1 Zeichen spaeter auf naechste Zeile umschalten, 481 // da sonst Zeilenattribute immer eine Zeile zu weit reichen. 482 while( (nEP < nPCnt) 483 && (nCpEnd > mpDrawEditEngine->GetTextLen( nEP ) + 1) ) 484 { 485 nCpEnd -= mpDrawEditEngine->GetTextLen( nEP ) + 1; 486 nEP++; 487 } 488 return ESelection( nSP, (sal_uInt16)nCpStart, nEP, (sal_uInt16)nCpEnd ); 489 } 490 491 // InsertTxbxStyAttrs() setzt die Style-Attribute in den uebergebenen ItemSet. 492 // Es werden die SW-Styles genommen, die Import-WW-Styles sind zu diesem 493 // Zeitpunkt schon destruiert. 494 // Die SW-Styles werden per Tiefensuche, d.h. mit Parent-Styles nach den 495 // in aSrcTab angegebenen Attributen untersucht. Diese werden per Clone 496 // dupliziert, bei den Duplikaten werden die Which-IDs 497 // gemaess der Tabelle aDstTab umgesetzt, damit die EditEngine sie nicht 498 // ignoriert. 499 // Es werden hierbei sowohl Para- wie auch Zeichen-Attribute in den 500 // ItemSet gestopft. 501 void SwWW8ImplReader::InsertTxbxStyAttrs( SfxItemSet& rS, sal_uInt16 nColl ) 502 { 503 SwWW8StyInf * pStyInf = GetStyle(nColl); 504 if( pStyInf != NULL && pStyInf->pFmt && pStyInf->bColl ) 505 { 506 const SfxPoolItem* pItem; 507 for( sal_uInt16 i = POOLATTR_BEGIN; i < POOLATTR_END; i++ ) 508 { 509 //If we are set in the source and not set in the destination 510 //then add it in. 511 if ( SFX_ITEM_SET == pStyInf->pFmt->GetItemState( 512 i, true, &pItem ) ) 513 { 514 SfxItemPool *pEditPool = rS.GetPool(); 515 sal_uInt16 nWhich = i; 516 sal_uInt16 nSlotId = rDoc.GetAttrPool().GetSlotId(nWhich); 517 if ( 518 nSlotId && nWhich != nSlotId && 519 0 != (nWhich = pEditPool->GetWhich(nSlotId)) && 520 nWhich != nSlotId && 521 ( SFX_ITEM_SET != rS.GetItemState(nWhich, false) ) 522 ) 523 { 524 SfxPoolItem* pCopy = pItem->Clone(); 525 pCopy->SetWhich( nWhich ); 526 rS.Put( *pCopy ); 527 delete pCopy; 528 } 529 } 530 } 531 } 532 533 } 534 535 static void lcl_StripFields(String &rString, long &rNewStartCp) 536 { 537 for(sal_uInt16 i=0; i < rString.Len(); i++) 538 { 539 if( 0x13 == rString.GetChar( i ) ) 540 { 541 do 542 { 543 rString.Erase( i, 1 ); 544 rNewStartCp++; 545 } 546 while( rString.Len() 547 && ( i < rString.Len()) 548 && (0x14 != rString.GetChar( i ) ) 549 && (0x15 != rString.GetChar( i ) ) ); 550 if( rString.Len() ) 551 { 552 if( 0x14 == rString.GetChar( i ) ) 553 { 554 rString.Erase( i, 1 ); 555 rNewStartCp++; 556 do 557 { 558 i++; 559 } 560 while( rString.Len() 561 && ( i < rString.Len()) 562 && (0x15 != rString.GetChar( i ) ) ); 563 if( i < rString.Len() ) 564 rString.Erase( i, 1 ); 565 } 566 else if( 0x15 == rString.GetChar( i ) ) 567 rString.Erase( i, 1 ); 568 } 569 } 570 } 571 } 572 573 class Chunk 574 { 575 private: 576 String msURL; 577 long mnStartPos; //0x13 578 long mnEndPos; //0x15 579 public: 580 explicit Chunk(long nStart, const String &rURL) 581 : msURL(rURL), mnStartPos(nStart) {} 582 Chunk(const Chunk &rChunk) 583 : msURL(rChunk.msURL), mnStartPos(rChunk.mnStartPos), 584 mnEndPos(rChunk.mnEndPos) {} 585 Chunk& operator=(const Chunk &rChunk) 586 { 587 msURL = rChunk.msURL; 588 mnStartPos = rChunk.mnStartPos; 589 mnEndPos = rChunk.mnEndPos; 590 return *this; 591 } 592 void SetEndPos(long nEnd) { mnEndPos = nEnd; } 593 long GetStartPos() const {return mnStartPos;} 594 long GetEndPos() const {return mnEndPos;} 595 const String &GetURL() const {return msURL;} 596 void Adjust(xub_StrLen nAdjust) 597 { 598 mnStartPos-=nAdjust; 599 mnEndPos-=nAdjust; 600 } 601 }; 602 603 // InsertAttrsAsDrawingAttrs() setzt zwischen StartCp und EndCp die Attribute. 604 // Dabei werden Style-Attribute als harte Attribute, Absatz- und Zeichen- 605 // attribute gesetzt. 606 void SwWW8ImplReader::InsertAttrsAsDrawingAttrs(long nStartCp, long nEndCp, 607 ManTypes eType, bool bONLYnPicLocFc) 608 { 609 /* 610 Save and create new plcxman for this drawing object, of the type that 611 will include the para end mark inside a paragraph property range, as 612 drawing boxes have real paragraph marks as part of their text, while 613 normal writer has seperate nodes for each paragraph and so has no actual 614 paragraph mark as part of the paragraph text. 615 */ 616 WW8ReaderSave aSave(this); 617 pPlcxMan = new WW8PLCFMan(pSBase, eType, nStartCp, true); 618 619 WW8_CP nStart = pPlcxMan->Where(); 620 WW8_CP nNext, nEnd, nStartReplace=0; 621 622 bool bDoingSymbol = false; 623 sal_Unicode cReplaceSymbol = cSymbol; 624 625 SfxItemSet *pS = new SfxItemSet(mpDrawEditEngine->GetEmptyItemSet()); 626 WW8PLCFManResult aRes; 627 628 std::deque<Chunk> aChunks; 629 630 //Here store stack location 631 sal_uInt16 nCurrentCount = static_cast< sal_uInt16 >(pCtrlStck->Count()); 632 while (nStart < nEndCp) 633 { 634 //nStart is the beginning of the attributes for this range, and 635 //may be before the text itself. So watch out for that 636 WW8_CP nTxtStart = nStart; 637 if (nTxtStart < nStartCp) 638 nTxtStart = nStartCp; 639 // get position of next SPRM 640 bool bStartAttr = pPlcxMan->Get(&aRes); 641 nAktColl = pPlcxMan->GetColl(); 642 if (aRes.nSprmId) 643 { 644 if( bONLYnPicLocFc ) 645 { 646 if ( (68 == aRes.nSprmId) || (0x6A03 == aRes.nSprmId) ) 647 { 648 Read_PicLoc(aRes.nSprmId, aRes.pMemPos + 649 mpSprmParser->DistanceToData(aRes.nSprmId), 4); 650 // Ok, that's what we were looking for. Now let's get 651 // out of here! 652 break; 653 } 654 } 655 else if ( aRes.nSprmId && ( 656 (eFTN > aRes.nSprmId) || (0x0800 <= aRes.nSprmId) ) ) 657 { 658 //Here place them onto our usual stack and we will pop them 659 //off and convert them later 660 if (bStartAttr) 661 { 662 ImportSprm(aRes.pMemPos, aRes.nSprmId); 663 if (!bDoingSymbol && bSymbol == true) 664 { 665 bDoingSymbol = true; 666 nStartReplace = nTxtStart; 667 cReplaceSymbol = cSymbol; 668 } 669 } 670 else 671 { 672 EndSprm( aRes.nSprmId ); 673 if (bSymbol == false && bDoingSymbol) 674 { 675 bDoingSymbol = false; 676 String sTemp; 677 sTemp.Fill(writer_cast<xub_StrLen>( 678 nTxtStart - nStartReplace), cReplaceSymbol); 679 mpDrawEditEngine->QuickInsertText(sTemp, 680 GetESelection(nStartReplace - nStartCp, 681 nTxtStart - nStartCp ) ); 682 } 683 } 684 } 685 else if (aRes.nSprmId == eFLD) 686 { 687 if (bStartAttr) 688 { 689 sal_uInt16 nCount = static_cast< sal_uInt16 >(pCtrlStck->Count()); 690 if (maFieldStack.empty() && Read_Field(&aRes)) 691 { 692 String sURL; 693 for (sal_uInt16 nI = static_cast< sal_uInt16 >(pCtrlStck->Count()); nI > nCount; --nI) 694 { 695 const SfxPoolItem *pItem = ((*pCtrlStck)[nI-1])->pAttr; 696 sal_uInt16 nWhich = pItem->Which(); 697 if (nWhich == RES_TXTATR_INETFMT) 698 { 699 const SwFmtINetFmt *pURL = 700 (const SwFmtINetFmt *)pItem; 701 sURL = pURL->GetValue(); 702 } 703 pCtrlStck->DeleteAndDestroy(nI-1); 704 } 705 aChunks.push_back(Chunk(nStart, sURL)); 706 } 707 } 708 else 709 { 710 if (!maFieldStack.empty() && End_Field()) 711 aChunks.back().SetEndPos(nStart+1); 712 } 713 } 714 } 715 716 (*pPlcxMan)++; 717 nNext = pPlcxMan->Where(); 718 719 if( (nNext != nStart) && !bONLYnPicLocFc ) 720 { 721 nEnd = ( nNext < nEndCp ) ? nNext : nEndCp; 722 SfxItemPool *pEditPool = pS->GetPool(); 723 724 //Here read current properties and convert them into pS 725 //and put those attrs into the draw box if they can be converted 726 //to draw attributes 727 if (pCtrlStck->Count() - nCurrentCount) 728 { 729 for (sal_uInt16 i = nCurrentCount; i < pCtrlStck->Count(); i++) 730 { 731 const SfxPoolItem *pItem = ((*pCtrlStck)[i])->pAttr; 732 sal_uInt16 nWhich = pItem->Which(); 733 if( nWhich < RES_FLTRATTR_BEGIN || 734 nWhich >= RES_FLTRATTR_END ) 735 { 736 sal_uInt16 nSlotId = rDoc.GetAttrPool().GetSlotId(nWhich); 737 if ( 738 nSlotId && nWhich != nSlotId && 739 0 != (nWhich = pEditPool->GetWhich(nSlotId)) && 740 nWhich != nSlotId 741 ) 742 { 743 SfxPoolItem* pCopy = pItem->Clone(); 744 pCopy->SetWhich( nWhich ); 745 pS->Put( *pCopy ); 746 delete pCopy; 747 } 748 } 749 } 750 } 751 //Fill in the remainder from the style 752 InsertTxbxStyAttrs(*pS, nAktColl); 753 754 if( pS->Count() ) 755 { 756 mpDrawEditEngine->QuickSetAttribs( *pS, 757 GetESelection( nTxtStart - nStartCp, nEnd - nStartCp ) ); 758 delete pS; 759 pS = new SfxItemSet(mpDrawEditEngine->GetEmptyItemSet()); 760 } 761 } 762 nStart = nNext; 763 } 764 delete pS; 765 766 //pop off as far as recorded location just in case there were some left 767 //unclosed 768 for (sal_uInt16 nI = static_cast< sal_uInt16 >(pCtrlStck->Count()); nI > nCurrentCount; --nI) 769 pCtrlStck->DeleteAndDestroy(nI-1); 770 771 typedef std::deque<Chunk>::iterator myIter; 772 myIter aEnd = aChunks.end(); 773 for (myIter aIter = aChunks.begin(); aIter != aEnd; ++aIter) 774 { 775 ESelection aSel(GetESelection(aIter->GetStartPos()-nStartCp, 776 aIter->GetEndPos()-nStartCp)); 777 String aString(mpDrawEditEngine->GetText(aSel)); 778 xub_StrLen nOrigLen = aString.Len(); 779 long nDummy(0); 780 lcl_StripFields(aString, nDummy); 781 782 xub_StrLen nChanged; 783 if (aIter->GetURL().Len()) 784 { 785 SvxURLField aURL(aIter->GetURL(), aString, 786 SVXURLFORMAT_APPDEFAULT); 787 mpDrawEditEngine->QuickInsertField(SvxFieldItem(aURL, EE_FEATURE_FIELD), aSel); 788 nChanged = nOrigLen - 1; 789 } 790 else 791 { 792 mpDrawEditEngine->QuickInsertText(aString, aSel); 793 nChanged = nOrigLen - aString.Len(); 794 } 795 for (myIter aIter2 = aIter+1; aIter2 != aEnd; ++aIter2) 796 aIter2->Adjust(nChanged); 797 } 798 799 /* 800 Don't worry about the new pPlcxMan, the restorer removes it when 801 replacing the current one with the old one. 802 */ 803 aSave.Restore(this); 804 } 805 806 bool SwWW8ImplReader::GetTxbxTextSttEndCp(WW8_CP& rStartCp, WW8_CP& rEndCp, 807 sal_uInt16 nTxBxS, sal_uInt16 nSequence) 808 { 809 // rasch den TextBox-PLCF greifen 810 WW8PLCFspecial* pT = pPlcxMan ? pPlcxMan->GetTxbx() : 0; 811 if( !pT ) 812 { 813 ASSERT( !this, "+Wo ist der Grafik-Text (1) ?" ); 814 return false; 815 } 816 817 // ggfs. zuerst die richtige TextBox-Story finden 818 bool bCheckTextBoxStory = ( nTxBxS && pT->GetIMax() >= nTxBxS ); 819 if( bCheckTextBoxStory ) 820 pT->SetIdx( nTxBxS-1 ); 821 822 // dann Start und Ende ermitteln 823 void* pT0; 824 if( !pT->Get( rStartCp, pT0 ) ) 825 { 826 ASSERT( !this, "+Wo ist der Grafik-Text (2) ?" ); 827 return false; 828 } 829 830 if( bCheckTextBoxStory ) 831 { 832 bool bReusable = (0 != SVBT16ToShort( ((WW8_TXBXS*)pT0)->fReusable )); 833 while( bReusable ) 834 { 835 (*pT)++; 836 if( !pT->Get( rStartCp, pT0 ) ) 837 { 838 ASSERT( !this, "+Wo ist der Grafik-Text (2-a) ?" ); 839 return false; 840 } 841 bReusable = (0 != SVBT16ToShort( ((WW8_TXBXS*)pT0)->fReusable )); 842 } 843 } 844 (*pT)++; 845 if( !pT->Get( rEndCp, pT0 ) ) 846 { 847 ASSERT( !this, "+Wo ist der Grafik-Text (3) ?" ); 848 return false; 849 } 850 851 // jetzt ggfs. die passende Page in der Break-Table finden 852 if( bCheckTextBoxStory ) 853 { 854 // Sonderfall: gesamte(!) Kette soll ermittelt werden, 855 // dann sind wir hier schon fertig! 856 if( USHRT_MAX > nSequence ) 857 { 858 long nMinStartCp = rStartCp; 859 long nMaxEndCp = rEndCp; 860 // rasch den TextBox-Break-Deskriptor-PLCF greifen 861 pT = pPlcxMan->GetTxbxBkd(); 862 if (!pT) //It can occur on occasion, Caolan 863 return false; 864 865 // den ersten Eintrag fuer diese TextBox-Story finden 866 if( !pT->SeekPos( rStartCp ) ) 867 { 868 ASSERT( !this, "+Wo ist der Grafik-Text (4) ?" ); 869 return false; 870 } 871 // ggfs. entsprechende Anzahl Eintraege weitergehen 872 for(sal_uInt16 iSequence = 0; iSequence < nSequence; iSequence++) (*pT)++; 873 // dann die tatsaechlichen Start und Ende ermitteln 874 if( (!pT->Get( rStartCp, pT0 )) 875 || ( nMinStartCp > rStartCp ) ) 876 { 877 ASSERT( !this, "+Wo ist der Grafik-Text (5) ?" ); 878 return false; 879 } 880 if( rStartCp >= nMaxEndCp ) 881 rEndCp = rStartCp; // kein Error: leerer String! 882 else 883 { 884 (*pT)++; 885 if( (!pT->Get( rEndCp, pT0 )) 886 || ( nMaxEndCp < rEndCp-1 ) ) 887 { 888 ASSERT( !this, "+Wo ist der Grafik-Text (6) ?" ); 889 return false; 890 } 891 rEndCp -= 1; 892 } 893 } 894 else 895 rEndCp -= 1; 896 } 897 else 898 rEndCp -= 1; 899 return true; 900 } 901 902 // TxbxText() holt aus WW-File den Text und gibt diesen und den Anfangs- und 903 // den um -2 (bzw. -1 bei Ver8) korrigierten End-Cp zurueck 904 bool SwWW8ImplReader::GetRangeAsDrawingString(String& rString, long nStartCp, long nEndCp, ManTypes eType) 905 { 906 WW8_CP nOffset = pWwFib->GetBaseCp(eType); 907 908 bool bOk = false; 909 ASSERT(nStartCp <= nEndCp, "+Wo ist der Grafik-Text (7) ?"); 910 if (nStartCp == nEndCp) 911 rString.Erase(); // leerer String: durchaus denkbar! 912 else if (nStartCp < nEndCp) 913 { 914 // den Text einlesen: kann sich ueber mehrere Pieces erstrecken!!! 915 sal_uInt16 nLen = pSBase->WW8ReadString(*pStrm, rString, 916 nStartCp + nOffset, nEndCp - nStartCp, GetCurrentCharSet()); 917 ASSERT(nLen, "+Wo ist der Grafik-Text (8) ?"); 918 if (nLen) 919 { 920 bOk = true; 921 if( 0x0d == rString.GetChar(nLen - 1) ) 922 rString.Erase(nLen - 1); 923 924 rString.SearchAndReplaceAll( 0xb, 0xa ); 925 } 926 } 927 return bOk; 928 } 929 930 OutlinerParaObject* SwWW8ImplReader::ImportAsOutliner(String &rString, WW8_CP nStartCp, WW8_CP nEndCp, ManTypes eType) 931 { 932 OutlinerParaObject* pRet = 0; 933 934 if (GetRangeAsDrawingString( rString, nStartCp, nEndCp, eType )) 935 { 936 if (!mpDrawEditEngine) 937 mpDrawEditEngine = new EditEngine(0); 938 939 mpDrawEditEngine->SetText(rString); 940 InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType); 941 942 //Annotations typically begin with a (useless) 0x5 943 if ((eType == MAN_AND) && mpDrawEditEngine->GetTextLen()) 944 { 945 ESelection aFirstChar(0, 0, 0, 1); 946 if (mpDrawEditEngine->GetText( aFirstChar ) == String(sal_Unicode(0x5))) 947 mpDrawEditEngine->QuickDelete(aFirstChar); 948 } 949 950 EditTextObject* pTemporaryText = mpDrawEditEngine->CreateTextObject(); 951 pRet = new OutlinerParaObject(*pTemporaryText); 952 pRet->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT ); 953 delete pTemporaryText; 954 955 mpDrawEditEngine->SetText( aEmptyStr ); 956 mpDrawEditEngine->SetParaAttribs(0, mpDrawEditEngine->GetEmptyItemSet()); 957 958 //Strip out fields, leaving the result 959 long nDummy(0); 960 lcl_StripFields(rString, nDummy); 961 //Strip out word's special characters for the simple string 962 rString.EraseAllChars(0x1); 963 rString.EraseAllChars(0x5); 964 rString.EraseAllChars(0x8); 965 rString.SearchAndReplaceAllAscii("\007\007", String::CreateFromAscii("\007\012")); 966 rString.SearchAndReplaceAll(0x7, ' '); 967 968 } 969 970 return pRet; 971 } 972 973 // InsertTxbxText() fuegt fuer TextBoxen und CaptionBoxen den Text 974 // und die Attribute ein 975 SwFrmFmt* SwWW8ImplReader::InsertTxbxText(SdrTextObj* pTextObj, 976 Size* pObjSiz, sal_uInt16 nTxBxS, sal_uInt16 nSequence, long nPosCp, 977 SwFrmFmt* pOldFlyFmt, bool bMakeSdrGrafObj, bool& rbEraseTextObj, 978 bool* pbTestTxbxContainsText, long* pnStartCp, long* pnEndCp, 979 bool* pbContainsGraphics, SvxMSDffImportRec* pRecord) 980 { 981 SwFrmFmt* pFlyFmt = 0; 982 sal_uLong nOld = pStrm->Tell(); 983 984 ManTypes eType = pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX; 985 986 rbEraseTextObj = false; 987 988 String aString; 989 WW8_CP nStartCp, nEndCp; 990 bool bContainsGraphics = false; 991 bool bTextWasRead = GetTxbxTextSttEndCp( nStartCp, nEndCp, nTxBxS, 992 nSequence ) && GetRangeAsDrawingString( aString, nStartCp, nEndCp, eType ); 993 994 if (!mpDrawEditEngine) 995 mpDrawEditEngine = new EditEngine(0); 996 if( pObjSiz ) 997 mpDrawEditEngine->SetPaperSize( *pObjSiz ); 998 999 String aOrigString(aString); 1000 if( bTextWasRead ) 1001 { 1002 long nNewStartCp = nStartCp; 1003 lcl_StripFields(aString, nNewStartCp); 1004 1005 if (1 != aString.Len()) 1006 { 1007 if ( (STRING_NOTFOUND != aString.Search(0x1)) || 1008 (STRING_NOTFOUND != aString.Search(0x8)) ) 1009 { 1010 bContainsGraphics = true; 1011 } 1012 } 1013 else // May be a single graphic or object 1014 { 1015 bool bDone = true; 1016 switch( aString.GetChar(0) ) 1017 { 1018 case 0x1: 1019 if (!pbTestTxbxContainsText) 1020 { 1021 WW8ReaderSave aSave(this, nNewStartCp -1); 1022 bool bOldEmbeddObj = bEmbeddObj; 1023 //bEmbedd Ordinarily would have been set by field 1024 //parse, but this is impossible here so... 1025 bEmbeddObj = true; 1026 1027 // 1st look for OLE- or Graph-Indicator Sprms 1028 WW8PLCFx_Cp_FKP* pChp = pPlcxMan->GetChpPLCF(); 1029 WW8PLCFxDesc aDesc; 1030 pChp->GetSprms( &aDesc ); 1031 WW8SprmIter aSprmIter(aDesc.pMemPos, aDesc.nSprmsLen, 1032 *mpSprmParser); 1033 1034 const sal_uInt8* pParams = aSprmIter.GetAktParams(); 1035 for( int nLoop = 0; nLoop < 2; ++nLoop ) 1036 { 1037 while( aSprmIter.GetSprms() 1038 && (0 != (pParams = aSprmIter.GetAktParams())) ) 1039 { 1040 sal_uInt16 nAktId = aSprmIter.GetAktId(); 1041 switch( nAktId ) 1042 { 1043 case 75: 1044 case 118: 1045 case 0x080A: 1046 case 0x0856: 1047 Read_Obj(nAktId, pParams, 1); 1048 break; 1049 case 68: // Read_Pic() 1050 case 0x6A03: 1051 case 0x680E: 1052 Read_PicLoc(nAktId, pParams, 1); 1053 break; 1054 } 1055 aSprmIter++; 1056 } 1057 1058 //if( bRead_Obj || bRead_PicLoc ) break; 1059 if( !nLoop ) 1060 { 1061 pChp->GetPCDSprms( aDesc ); 1062 aSprmIter.SetSprms( aDesc.pMemPos, 1063 aDesc.nSprmsLen ); 1064 } 1065 //if( bRead_Obj || bRead_PicLoc ) break; 1066 } 1067 aSave.Restore(this); 1068 bEmbeddObj=bOldEmbeddObj; 1069 1070 // then import either an OLE of a Graphic 1071 if( bObj ) 1072 { 1073 if( bMakeSdrGrafObj && pTextObj && 1074 pTextObj->GetUpGroup() ) 1075 { 1076 // SdrOleObj/SdrGrafObj anstatt des 1077 // SdrTextObj in dessen Gruppe einsetzen 1078 1079 Graphic aGraph; 1080 SdrObject* pNew = ImportOleBase(aGraph); 1081 1082 if( !pNew ) 1083 { 1084 pNew = new SdrGrafObj; 1085 ((SdrGrafObj*)pNew)->SetGraphic(aGraph); 1086 } 1087 1088 GrafikCtor(); 1089 1090 pNew->SetModel( pDrawModel ); 1091 pNew->SetLogicRect( pTextObj->GetCurrentBoundRect() ); 1092 pNew->SetLayer( pTextObj->GetLayer() ); 1093 1094 pTextObj->GetUpGroup()->GetSubList()-> 1095 ReplaceObject(pNew, pTextObj->GetOrdNum()); 1096 } 1097 else 1098 pFlyFmt = ImportOle(); 1099 bObj = false; 1100 } 1101 else 1102 { 1103 InsertAttrsAsDrawingAttrs(nNewStartCp, nNewStartCp+1, 1104 eType, true); 1105 pFlyFmt = ImportGraf(bMakeSdrGrafObj ? pTextObj : 0, 1106 pOldFlyFmt); 1107 } 1108 } 1109 break; 1110 case 0x8: 1111 if ( (!pbTestTxbxContainsText) && (!bObj) ) 1112 pFlyFmt = Read_GrafLayer( nPosCp ); 1113 break; 1114 default: 1115 bDone = false; 1116 break; 1117 } 1118 1119 if( bDone ) 1120 { 1121 if( pFlyFmt ) 1122 { 1123 if( pRecord ) 1124 { 1125 SfxItemSet aFlySet( rDoc.GetAttrPool(), 1126 RES_FRMATR_BEGIN, RES_FRMATR_END-1 ); 1127 1128 Rectangle aInnerDist( pRecord->nDxTextLeft, 1129 pRecord->nDyTextTop, 1130 pRecord->nDxTextRight, 1131 pRecord->nDyTextBottom ); 1132 MatchSdrItemsIntoFlySet( pTextObj, 1133 aFlySet, 1134 pRecord->eLineStyle, 1135 pRecord->eShapeType, 1136 aInnerDist ); 1137 1138 pFlyFmt->SetFmtAttr( aFlySet ); 1139 1140 MapWrapIntoFlyFmt(pRecord, pFlyFmt); 1141 } 1142 } 1143 aString.Erase(); 1144 rbEraseTextObj = (0 != pFlyFmt); 1145 } 1146 } 1147 } 1148 1149 if( pnStartCp ) 1150 *pnStartCp = nStartCp; 1151 if( pnEndCp ) 1152 *pnEndCp = nEndCp; 1153 1154 if( pbTestTxbxContainsText ) 1155 *pbTestTxbxContainsText = bTextWasRead && ! rbEraseTextObj; 1156 else if( !rbEraseTextObj ) 1157 { 1158 if( bTextWasRead ) 1159 { 1160 mpDrawEditEngine->SetText(aOrigString); 1161 InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType); 1162 } 1163 1164 bool bVertical = pTextObj->IsVerticalWriting() ? true : false; 1165 EditTextObject* pTemporaryText = mpDrawEditEngine->CreateTextObject(); 1166 OutlinerParaObject* pOp = new OutlinerParaObject(*pTemporaryText); 1167 pOp->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT ); 1168 pOp->SetVertical( bVertical ); 1169 delete pTemporaryText; 1170 pTextObj->NbcSetOutlinerParaObject( pOp ); 1171 pTextObj->SetVerticalWriting(bVertical); 1172 1173 // Fuer die naechste Textbox noch die alten Absatz-Attribute 1174 // und Styles entfernen, sonst startet die naechste Box 1175 // mit falschen Attributen. 1176 // Vorgehen: Text loeschen = auf 1 Absatz reduzieren 1177 // und an diesem Absatz die Absatzattribute und Styles loeschen 1178 // (Empfehlung JOE) 1179 mpDrawEditEngine->SetText( aEmptyStr ); 1180 mpDrawEditEngine->SetParaAttribs(0, mpDrawEditEngine->GetEmptyItemSet()); 1181 } 1182 1183 pStrm->Seek( nOld ); 1184 if (pbContainsGraphics) 1185 *pbContainsGraphics = bContainsGraphics; 1186 return pFlyFmt; 1187 } 1188 1189 1190 bool SwWW8ImplReader::TxbxChainContainsRealText(sal_uInt16 nTxBxS, long& rStartCp, 1191 long& rEndCp) 1192 { 1193 bool bErase, bContainsText; 1194 InsertTxbxText( 0,0,nTxBxS,USHRT_MAX,0,0,0, bErase, &bContainsText, 1195 &rStartCp, &rEndCp ); 1196 return bContainsText; 1197 } 1198 1199 1200 // TextBoxes only for Ver67 !! 1201 SdrObject* SwWW8ImplReader::ReadTxtBox( WW8_DPHEAD* pHd, const WW8_DO* pDo, 1202 SfxAllItemSet &rSet) 1203 { 1204 bool bDummy; 1205 WW8_DP_TXTBOX aTxtB; 1206 1207 if( !ReadGrafStart( (void*)&aTxtB, sizeof( aTxtB ), pHd, pDo, rSet ) ) 1208 return 0; 1209 1210 Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2, 1211 (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 ); 1212 Point aP1( aP0 ); 1213 aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa ); 1214 aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya ); 1215 1216 SdrObject* pObj = new SdrRectObj( OBJ_TEXT, Rectangle( aP0, aP1 ) ); 1217 pObj->SetModel( pDrawModel ); 1218 pObj->NbcSetSnapRect(Rectangle(aP0, aP1)); 1219 Size aSize( (sal_Int16)SVBT16ToShort( pHd->dxa ) , 1220 (sal_Int16)SVBT16ToShort( pHd->dya ) ); 1221 1222 long nStartCpFly,nEndCpFly; 1223 bool bContainsGraphics; 1224 InsertTxbxText(PTR_CAST(SdrTextObj,pObj), &aSize, 0, 0, 0, 0, false, 1225 bDummy,0,&nStartCpFly,&nEndCpFly,&bContainsGraphics); 1226 1227 SetStdAttr( rSet, aTxtB.aLnt, aTxtB.aShd ); 1228 SetFill( rSet, aTxtB.aFill ); 1229 1230 rSet.Put( SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE ) ); 1231 rSet.Put( SdrTextAutoGrowWidthItem(false)); 1232 rSet.Put( SdrTextAutoGrowHeightItem(false)); 1233 rSet.Put( SdrTextLeftDistItem( MIN_BORDER_DIST*2 ) ); 1234 rSet.Put( SdrTextRightDistItem( MIN_BORDER_DIST*2 ) ); 1235 rSet.Put( SdrTextUpperDistItem( MIN_BORDER_DIST ) ); 1236 rSet.Put( SdrTextLowerDistItem( MIN_BORDER_DIST ) ); 1237 1238 return pObj; 1239 } 1240 1241 SdrObject* SwWW8ImplReader::ReadCaptionBox( WW8_DPHEAD* pHd, const WW8_DO* pDo, 1242 SfxAllItemSet &rSet) 1243 { 1244 static SdrCaptionType aCaptA[] = { SDRCAPT_TYPE1, SDRCAPT_TYPE2, 1245 SDRCAPT_TYPE3, SDRCAPT_TYPE4 }; 1246 1247 WW8_DP_CALLOUT_TXTBOX aCallB; 1248 1249 if( !ReadGrafStart( (void*)&aCallB, sizeof( aCallB ), pHd, pDo, rSet ) ) 1250 return 0; 1251 1252 sal_uInt16 nCount = SVBT16ToShort( aCallB.dpPolyLine.aBits1 ) >> 1 & 0x7fff; 1253 SVBT16 *pP = new SVBT16[nCount * 2]; 1254 pStrm->Read( pP, nCount * 4 ); // Punkte einlesen 1255 sal_uInt8 nTyp = (sal_uInt8)nCount - 1; 1256 if( nTyp == 1 && SVBT16ToShort( pP[0] ) == SVBT16ToShort( pP[2] ) ) 1257 nTyp = 0; 1258 1259 Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + 1260 (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.xa ) + nDrawXOfs2, 1261 (sal_Int16)SVBT16ToShort( pHd->ya ) 1262 + (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.ya ) + nDrawYOfs2 ); 1263 Point aP1( aP0 ); 1264 aP1.X() += (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dxa ); 1265 aP1.Y() += (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dya ); 1266 Point aP2( (sal_Int16)SVBT16ToShort( pHd->xa ) 1267 + (sal_Int16)SVBT16ToShort( aCallB.dpheadPolyLine.xa ) 1268 + nDrawXOfs2 + (sal_Int16)SVBT16ToShort( pP[0] ), 1269 (sal_Int16)SVBT16ToShort( pHd->ya ) 1270 + (sal_Int16)SVBT16ToShort( aCallB.dpheadPolyLine.ya ) 1271 + nDrawYOfs2 + (sal_Int16)SVBT16ToShort( pP[1] ) ); 1272 delete[] pP; 1273 1274 SdrCaptionObj* pObj = new SdrCaptionObj( Rectangle( aP0, aP1 ), aP2 ); 1275 pObj->SetModel( pDrawModel ); 1276 pObj->NbcSetSnapRect(Rectangle(aP0, aP1)); 1277 Size aSize( (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dxa ), 1278 (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dya ) ); 1279 bool bEraseThisObject; 1280 1281 InsertTxbxText(pObj, &aSize, 0, 0, 0, 0, false, bEraseThisObject ); 1282 1283 if( SVBT16ToShort( aCallB.dptxbx.aLnt.lnps ) != 5 ) // Umrandung sichtbar ? 1284 SetStdAttr( rSet, aCallB.dptxbx.aLnt, aCallB.dptxbx.aShd ); 1285 else // nein -> Nimm Linie 1286 SetStdAttr( rSet, aCallB.dpPolyLine.aLnt, aCallB.dptxbx.aShd ); 1287 SetFill( rSet, aCallB.dptxbx.aFill ); 1288 rSet.Put( SdrCaptionTypeItem( aCaptA[nTyp] ) ); 1289 1290 return pObj; 1291 } 1292 1293 1294 SdrObject *SwWW8ImplReader::ReadGroup( WW8_DPHEAD* pHd, const WW8_DO* pDo, 1295 SfxAllItemSet &rSet) 1296 { 1297 sal_Int16 nGrouped; 1298 1299 if( !ReadGrafStart( (void*)&nGrouped, sizeof( nGrouped ), pHd, pDo, rSet ) ) 1300 return 0; 1301 1302 #ifdef OSL_BIGENDIAN 1303 nGrouped = (sal_Int16)SWAPSHORT( nGrouped ); 1304 #endif 1305 1306 nDrawXOfs = nDrawXOfs + (sal_Int16)SVBT16ToShort( pHd->xa ); 1307 nDrawYOfs = nDrawYOfs + (sal_Int16)SVBT16ToShort( pHd->ya ); 1308 1309 SdrObject* pObj = new SdrObjGroup; 1310 1311 short nLeft = (sal_Int16)SVBT16ToShort( pHd->cb ) - sizeof( WW8_DPHEAD ); 1312 for (int i = 0; i < nGrouped; i++) 1313 { 1314 SfxAllItemSet aSet(pDrawModel->GetItemPool()); 1315 if (SdrObject *pObject = ReadGrafPrimitive(nLeft, pDo, aSet)) 1316 { 1317 // #116150# 1318 // first add and then set ItemSet 1319 SdrObjList *pSubGroup = pObj->GetSubList(); 1320 ASSERT(pSubGroup, "Why no sublist available?"); 1321 if (pSubGroup) 1322 pSubGroup->InsertObject(pObject, 0); 1323 pObject->SetMergedItemSetAndBroadcast(aSet); 1324 } 1325 } 1326 1327 nDrawXOfs = nDrawXOfs - (sal_Int16)SVBT16ToShort( pHd->xa ); 1328 nDrawYOfs = nDrawYOfs - (sal_Int16)SVBT16ToShort( pHd->ya ); 1329 1330 return pObj; 1331 } 1332 1333 SdrObject* SwWW8ImplReader::ReadGrafPrimitive( short& rLeft, const WW8_DO* pDo, 1334 SfxAllItemSet &rSet) 1335 { 1336 //cmc: This whole archaic word 6 graphic import can probably be refactored 1337 //into an object hierarachy with a little effort. 1338 SdrObject *pRet=0; 1339 WW8_DPHEAD aHd; // Lese Draw-Primitive-Header 1340 pStrm->Read(&aHd, sizeof(WW8_DPHEAD)); 1341 1342 if( rLeft >= SVBT16ToShort(aHd.cb) ) // Vorsichtsmassmahme 1343 { 1344 rSet.Put(SwFmtSurround(SURROUND_THROUGHT)); 1345 switch (SVBT16ToShort(aHd.dpk) & 0xff ) 1346 { 1347 case 0: 1348 pRet = ReadGroup( &aHd, pDo, rSet ); 1349 break; 1350 case 1: 1351 pRet = ReadLine( &aHd, pDo, rSet ); 1352 break; 1353 case 2: 1354 pRet = ReadTxtBox( &aHd, pDo, rSet ); 1355 break; 1356 case 3: 1357 pRet = ReadRect( &aHd, pDo, rSet ); 1358 break; 1359 case 4: 1360 pRet = ReadElipse( &aHd, pDo, rSet ); 1361 break; 1362 case 5: 1363 pRet = ReadArc( &aHd, pDo, rSet ); 1364 break; 1365 case 6: 1366 pRet = ReadPolyLine( &aHd, pDo, rSet ); 1367 break; 1368 case 7: 1369 pRet = ReadCaptionBox( &aHd, pDo, rSet ); 1370 break; 1371 default: // unbekannt 1372 pStrm->SeekRel(SVBT16ToShort(aHd.cb) - sizeof(WW8_DPHEAD)); 1373 break; 1374 } 1375 } 1376 else 1377 { 1378 ASSERT( !this, "+Grafik-Overlap" ); 1379 } 1380 rLeft = rLeft - SVBT16ToShort( aHd.cb ); 1381 return pRet; 1382 } 1383 1384 void SwWW8ImplReader::ReadGrafLayer1( WW8PLCFspecial* pPF, long nGrafAnchorCp ) 1385 { 1386 pPF->SeekPos( nGrafAnchorCp ); 1387 WW8_FC nStartFc; 1388 void* pF0; 1389 if( !pPF->Get( nStartFc, pF0 ) ) 1390 { 1391 ASSERT( !this, "+Wo ist die Grafik (2) ?" ); 1392 return; 1393 } 1394 WW8_FDOA* pF = (WW8_FDOA*)pF0; 1395 if( !SVBT32ToUInt32( pF->fc ) ) 1396 { 1397 ASSERT( !this, "+Wo ist die Grafik (3) ?" ); 1398 return; 1399 } 1400 WW8_DO aDo; 1401 pStrm->Seek( SVBT32ToUInt32( pF->fc ) ); // Lese Draw-Header 1402 pStrm->Read( &aDo, sizeof( WW8_DO ) ); 1403 1404 short nLeft = SVBT16ToShort( aDo.cb ) - sizeof( WW8_DO ); 1405 while (nLeft > static_cast<short>(sizeof(WW8_DPHEAD))) 1406 { 1407 SfxAllItemSet aSet( pDrawModel->GetItemPool() ); 1408 if (SdrObject *pObject = ReadGrafPrimitive( nLeft, &aDo, aSet )) 1409 { 1410 pWWZOrder->InsertDrawingObject(pObject, SVBT16ToShort(aDo.dhgt)); 1411 SwFrmFmt *pFrm = rDoc.Insert( *pPaM, *pObject, &aSet, NULL); 1412 pObject->SetMergedItemSet(aSet); 1413 pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFrm); 1414 } 1415 } 1416 } 1417 1418 const WW8_BordersSO &WW8_BordersSO::Get0x01LineMatch(eBorderCode eCode) 1419 { 1420 /* 1421 // Linien-Defaults in Twips: fruehere Writer-Defaults, 1422 // siehe auch <editeng/boxitem.hxx> 1423 #define DEF_LINE_WIDTH_0 1 1424 #define DEF_LINE_WIDTH_1 20 1425 #define DEF_LINE_WIDTH_2 50 1426 #define DEF_LINE_WIDTH_3 80 1427 #define DEF_LINE_WIDTH_4 100 1428 #define DEF_LINE_WIDTH_5 10 1429 1430 #define DEF_MAX_LINE_WIDHT DEF_LINE_WIDTH_4 1431 #define DEF_MAX_LINE_DIST DEF_LINE_WIDTH_2 1432 1433 #define DEF_DOUBLE_LINE0_OUT DEF_LINE_WIDTH_0 1434 #define DEF_DOUBLE_LINE0_IN DEF_LINE_WIDTH_0 1435 #define DEF_DOUBLE_LINE0_DIST DEF_LINE_WIDTH_1 1436 1437 #define DEF_DOUBLE_LINE1_OUT DEF_LINE_WIDTH_1 1438 #define DEF_DOUBLE_LINE1_IN DEF_LINE_WIDTH_1 1439 #define DEF_DOUBLE_LINE1_DIST DEF_LINE_WIDTH_1 1440 1441 #define DEF_DOUBLE_LINE2_OUT DEF_LINE_WIDTH_2 1442 #define DEF_DOUBLE_LINE2_IN DEF_LINE_WIDTH_2 1443 #define DEF_DOUBLE_LINE2_DIST DEF_LINE_WIDTH_2 1444 1445 #define DEF_DOUBLE_LINE3_OUT DEF_LINE_WIDTH_2 1446 #define DEF_DOUBLE_LINE3_IN DEF_LINE_WIDTH_1 1447 #define DEF_DOUBLE_LINE3_DIST DEF_LINE_WIDTH_2 1448 1449 #define DEF_DOUBLE_LINE4_OUT DEF_LINE_WIDTH_1 1450 #define DEF_DOUBLE_LINE4_IN DEF_LINE_WIDTH_2 1451 #define DEF_DOUBLE_LINE4_DIST DEF_LINE_WIDTH_1 1452 1453 #define DEF_DOUBLE_LINE5_OUT DEF_LINE_WIDTH_3 1454 #define DEF_DOUBLE_LINE5_IN DEF_LINE_WIDTH_2 1455 #define DEF_DOUBLE_LINE5_DIST DEF_LINE_WIDTH_2 1456 1457 #define DEF_DOUBLE_LINE6_OUT DEF_LINE_WIDTH_2 1458 #define DEF_DOUBLE_LINE6_IN DEF_LINE_WIDTH_3 1459 #define DEF_DOUBLE_LINE6_DIST DEF_LINE_WIDTH_2 1460 1461 #define DEF_DOUBLE_LINE7_OUT DEF_LINE_WIDTH_0 1462 #define DEF_DOUBLE_LINE7_IN DEF_LINE_WIDTH_0 1463 #define DEF_DOUBLE_LINE7_DIST DEF_LINE_WIDTH_2 1464 1465 #define DEF_DOUBLE_LINE8_OUT DEF_LINE_WIDTH_1 1466 #define DEF_DOUBLE_LINE8_IN DEF_LINE_WIDTH_0 1467 #define DEF_DOUBLE_LINE8_DIST DEF_LINE_WIDTH_2 1468 1469 #define DEF_DOUBLE_LINE9_OUT DEF_LINE_WIDTH_2 1470 #define DEF_DOUBLE_LINE9_IN DEF_LINE_WIDTH_0 1471 #define DEF_DOUBLE_LINE9_DIST DEF_LINE_WIDTH_2 1472 1473 #define DEF_DOUBLE_LINE10_OUT DEF_LINE_WIDTH_3 1474 #define DEF_DOUBLE_LINE10_IN DEF_LINE_WIDTH_0 1475 #define DEF_DOUBLE_LINE10_DIST DEF_LINE_WIDTH_2 1476 */ 1477 // Deklarationen gemaess BOXITEM.HXX 1478 static const WW8_BordersSO aLineTabVer8[] = 1479 { 1480 /* 0*/ { DEF_LINE_WIDTH_0, 0, 0 }, 1481 /* 1*/ { DEF_LINE_WIDTH_1, 0, 0 }, 1482 /* 2*/ { DEF_LINE_WIDTH_2, 0, 0 }, 1483 /* 3*/ { DEF_LINE_WIDTH_3, 0, 0 }, 1484 /* 4*/ { DEF_LINE_WIDTH_4, 0, 0 }, 1485 /* 5*/ { DEF_LINE_WIDTH_5, 0, 0 }, 1486 /* 6*/ { DEF_DOUBLE_LINE0_OUT, DEF_DOUBLE_LINE0_IN, DEF_DOUBLE_LINE0_DIST }, 1487 /* 7*/ { DEF_DOUBLE_LINE1_OUT, DEF_DOUBLE_LINE1_IN, DEF_DOUBLE_LINE1_DIST }, 1488 /* 8*/ { DEF_DOUBLE_LINE2_OUT, DEF_DOUBLE_LINE2_IN, DEF_DOUBLE_LINE2_DIST }, 1489 /* 9*/ { DEF_DOUBLE_LINE3_OUT, DEF_DOUBLE_LINE3_IN, DEF_DOUBLE_LINE3_DIST }, 1490 /*10*/ { DEF_DOUBLE_LINE4_OUT, DEF_DOUBLE_LINE4_IN, DEF_DOUBLE_LINE4_DIST }, 1491 /*11*/ { DEF_DOUBLE_LINE5_OUT, DEF_DOUBLE_LINE5_IN, DEF_DOUBLE_LINE5_DIST }, 1492 /*12*/ { DEF_DOUBLE_LINE6_OUT, DEF_DOUBLE_LINE6_IN, DEF_DOUBLE_LINE6_DIST }, 1493 /*13*/ { DEF_DOUBLE_LINE7_OUT, DEF_DOUBLE_LINE7_IN, DEF_DOUBLE_LINE7_DIST }, 1494 /*14*/ { DEF_DOUBLE_LINE8_OUT, DEF_DOUBLE_LINE8_IN, DEF_DOUBLE_LINE8_DIST }, 1495 /*15*/ { DEF_DOUBLE_LINE9_OUT, DEF_DOUBLE_LINE9_IN, DEF_DOUBLE_LINE9_DIST }, 1496 /*16*/ { DEF_DOUBLE_LINE10_OUT,DEF_DOUBLE_LINE10_IN,DEF_DOUBLE_LINE10_DIST} 1497 }; 1498 size_t nPos = static_cast<size_t>(eCode); 1499 ASSERT(nPos < sizeof(aLineTabVer8), "Impossible"); 1500 if (nPos >= sizeof(aLineTabVer8)) 1501 eCode = single0; 1502 return aLineTabVer8[eCode]; 1503 } 1504 1505 sal_Int32 SwMSDffManager::GetEscherLineMatch(MSO_LineStyle eStyle, 1506 MSO_SPT eShapeType, sal_Int32 &rThick) 1507 { 1508 sal_Int32 nOutsideThick = 0; 1509 /* 1510 Beachte: im Gegensatz zu den Winword-ueblichen Tabellen- und 1511 Rahmen-Randbreiten-Angaben, bei denen jeweils aus der Staerke *einer* 1512 Linie die Gesamt-Randbreite zu errechnen ist, liegen die aus dem ESCHER 1513 stammenden Daten bereits als Gesamt-Breite [twips] vor! 1514 1515 Der Winword default ist 15 tw. Wir nehmen hierfuer unsere 20 tw Linie. ( 1516 0.75 pt uns 1.0 pt sehen sich auf dem Ausdruck naemlich aehnlicher als 1517 etwas 0.75 pt und unsere 0.05 pt Haarlinie. ) Die Haarlinie setzen wir nur 1518 bei Winword-Staerken bis zu maximal 0.5 pt ein. 1519 */ 1520 switch( eStyle ) 1521 { 1522 case mso_lineTriple: 1523 case mso_lineSimple: 1524 nOutsideThick = eShapeType != mso_sptTextBox ? rThick : rThick/2; 1525 break; 1526 case mso_lineDouble: 1527 if (eShapeType == mso_sptTextBox) 1528 { 1529 nOutsideThick = rThick/6; 1530 rThick = rThick*2/3; 1531 } 1532 else 1533 nOutsideThick = rThick*2/3; 1534 break; 1535 case mso_lineThickThin: 1536 if (eShapeType == mso_sptTextBox) 1537 { 1538 nOutsideThick = rThick*3/10; 1539 rThick = rThick*4/5; 1540 } 1541 else 1542 nOutsideThick = rThick*4/5; 1543 break; 1544 case mso_lineThinThick: 1545 { 1546 if (eShapeType == mso_sptTextBox) 1547 { 1548 nOutsideThick = rThick/10; 1549 rThick = rThick*3/5; 1550 } 1551 else 1552 nOutsideThick = rThick*3/5; 1553 } 1554 break; 1555 default: 1556 break; 1557 } 1558 return nOutsideThick; 1559 } 1560 1561 //Returns the thickness of the line outside the frame, the logic of 1562 //words positioning of borders around floating objects is that of a 1563 //disturbed mind. 1564 sal_Int32 SwWW8ImplReader::MatchSdrBoxIntoFlyBoxItem(const Color& rLineColor, 1565 MSO_LineStyle eLineStyle, MSO_SPT eShapeType, sal_Int32 &rLineThick, 1566 SvxBoxItem& rBox ) 1567 { 1568 sal_Int32 nOutsideThick = 0; 1569 if( !rLineThick ) 1570 return nOutsideThick; 1571 1572 WW8_BordersSO::eBorderCode nIdx = WW8_BordersSO::none; 1573 1574 sal_Int32 nLineThick=rLineThick; 1575 nOutsideThick = SwMSDffManager::GetEscherLineMatch(eLineStyle, 1576 eShapeType, rLineThick); 1577 1578 /* 1579 Beachte: im Gegensatz zu den Winword-ueblichen Tabellen- und 1580 Rahmen-Randbreiten-Angaben, bei denen jeweils aus der Staerke *einer* 1581 Linie die Gesamt-Randbreite zu errechnen ist, liegen die aus dem ESCHER 1582 stammenden Daten bereits als Gesamt-Breite [twips] vor! 1583 1584 Der Winword default ist 15 tw. Wir nehmen hierfuer unsere 20 tw Linie. ( 1585 0.75 pt uns 1.0 pt sehen sich auf dem Ausdruck naemlich aehnlicher als 1586 etwas 0.75 pt und unsere 0.05 pt Haarlinie. ) Die Haarlinie setzen wir nur 1587 bei Winword-Staerken bis zu maximal 0.5 pt ein. 1588 */ 1589 switch( +eLineStyle ) 1590 { 1591 // zuerst die Einzel-Linien 1592 case mso_lineSimple: 1593 if (nLineThick < 10) 1594 nIdx = WW8_BordersSO::single0;// 1 Twip bei uns 1595 else if (nLineThick < 20) 1596 nIdx = WW8_BordersSO::single5;// 10 Twips bei uns 1597 else if (nLineThick < 50) 1598 nIdx = WW8_BordersSO::single1;// 20 Twips 1599 else if (nLineThick < 80) 1600 nIdx = WW8_BordersSO::single2;// 50 1601 else if (nLineThick < 100) 1602 nIdx = WW8_BordersSO::single3;// 80 1603 else if (nLineThick <150) 1604 nIdx = WW8_BordersSO::single4;// 100 1605 // Pfusch: fuer die ganz dicken Linien muessen wir doppelte Linien 1606 // malen, weil unsere Einfach-Linie nicht dicker als 5 Punkt wird 1607 else if (nLineThick <180) 1608 nIdx = WW8_BordersSO::double2;// 150 1609 else 1610 nIdx = WW8_BordersSO::double5;// 180 1611 break; 1612 // dann die Doppel-Linien, fuer die wir feine Entsprechungen haben :-))) 1613 case mso_lineDouble: 1614 if (nLineThick < 60) 1615 nIdx = WW8_BordersSO::double0;// 22 Twips bei uns 1616 else if (nLineThick < 135) 1617 nIdx = WW8_BordersSO::double7;// some more space 1618 else if (nLineThick < 180) 1619 nIdx = WW8_BordersSO::double1;// 60 1620 else 1621 nIdx = WW8_BordersSO::double2;// 150 1622 break; 1623 case mso_lineThickThin: 1624 if (nLineThick < 87) 1625 nIdx = WW8_BordersSO::double8;// 71 Twips bei uns 1626 else if (nLineThick < 117) 1627 nIdx = WW8_BordersSO::double9;// 101 1628 else if (nLineThick < 166) 1629 nIdx = WW8_BordersSO::double10;// 131 1630 else 1631 nIdx = WW8_BordersSO::double5;// 180 1632 break; 1633 case mso_lineThinThick: 1634 if (nLineThick < 137) 1635 nIdx = WW8_BordersSO::double4;// 90 Twips bei uns 1636 else 1637 nIdx = WW8_BordersSO::double6;// 180 1638 break; 1639 // zu guter Letzt die Dreifach-Linien, an deren Stelle wir eine 1640 // Doppel-Linie setzen 1641 case mso_lineTriple: 1642 if (nLineThick < 46) 1643 nIdx = WW8_BordersSO::double0;// 22 Twips bei uns 1644 else if (nLineThick < 106) 1645 nIdx = WW8_BordersSO::double1;// 60 1646 else if (nLineThick < 166) 1647 nIdx = WW8_BordersSO::double2;// 150 1648 else 1649 nIdx = WW8_BordersSO::double5;// 180 1650 break; 1651 // no line style is set 1652 case (MSO_LineStyle)USHRT_MAX: 1653 break; 1654 // erroneously not implemented line style is set 1655 default: 1656 ASSERT(!this, "eLineStyle is not (yet) implemented!"); 1657 break; 1658 } 1659 1660 if (WW8_BordersSO::none != nIdx) 1661 { 1662 SvxBorderLine aLine; 1663 aLine.SetColor( rLineColor ); 1664 1665 const WW8_BordersSO& rBorders = WW8_BordersSO::Get0x01LineMatch(nIdx); 1666 1667 aLine.SetOutWidth(rBorders.mnOut); 1668 aLine.SetInWidth (rBorders.mnIn); 1669 aLine.SetDistance(rBorders.mnDist); 1670 1671 for(sal_uInt16 nLine = 0; nLine < 4; ++nLine) 1672 rBox.SetLine(new SvxBorderLine( aLine ), nLine); 1673 } 1674 1675 return nOutsideThick; 1676 } 1677 1678 #define WW8ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue() 1679 1680 void SwWW8ImplReader::MatchSdrItemsIntoFlySet( SdrObject* pSdrObj, 1681 SfxItemSet& rFlySet, MSO_LineStyle eLineStyle, MSO_SPT eShapeType, 1682 Rectangle& rInnerDist ) 1683 { 1684 /* 1685 am Rahmen zu setzende Frame-Attribute 1686 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1687 SwFmtFrmSize falls noch nicht gesetzt, hier setzen 1688 SvxLRSpaceItem hier setzen 1689 SvxULSpaceItem hier setzen 1690 SvxOpaqueItem (Derzeit bei Rahmen nicht moeglich! khz 10.2.1999) 1691 SwFmtSurround bereits gesetzt 1692 SwFmtVertOrient bereits gesetzt 1693 SwFmtHoriOrient bereits gesetzt 1694 SwFmtAnchor bereits gesetzt 1695 SvxBoxItem hier setzen 1696 SvxBrushItem hier setzen 1697 SvxShadowItem hier setzen 1698 */ 1699 1700 // 1. GrafikObjekt des Docs? 1701 GrafikCtor(); 1702 1703 const SfxItemSet& rOldSet = pSdrObj->GetMergedItemSet(); 1704 1705 // einige Items koennen direkt so uebernommen werden 1706 const sal_uInt16 nDirectMatch = 2; 1707 static RES_FRMATR __READONLY_DATA aDirectMatch[ nDirectMatch ] = 1708 { 1709 RES_LR_SPACE, // Aussenabstand links/rechts: SvxLRSpaceItem 1710 RES_UL_SPACE // Aussenabstand Oben/unten: SvxULSpaceItem 1711 }; 1712 const SfxPoolItem* pPoolItem; 1713 for(sal_uInt16 nItem = 0; nItem < nDirectMatch; ++nItem) 1714 if( SFX_ITEM_SET == rOldSet.GetItemState( 1715 static_cast< sal_uInt16 >(aDirectMatch[ nItem ]), false, &pPoolItem) ) 1716 { 1717 rFlySet.Put( *pPoolItem ); 1718 } 1719 1720 1721 // jetzt die Umrandung berechnen und die Box bauen: Das Mass wird fuer die 1722 // Rahmen-GROESSE benoetigt! 1723 SvxBoxItem aBox(sw::util::ItemGet<SvxBoxItem>(rFlySet, RES_BOX)); 1724 // dashed oder solid wird zu solid 1725 sal_Int32 nLineThick = 0, nOutside=0; 1726 1727 // check if LineStyle is *really* set! 1728 const SfxPoolItem* pItem; 1729 1730 SfxItemState eState = rOldSet.GetItemState(XATTR_LINESTYLE,true,&pItem); 1731 if( eState == SFX_ITEM_SET ) 1732 { 1733 // Now, that we know there is a line style we will make use the 1734 // parameter given to us when calling the method... :-) 1735 const Color aLineColor = static_cast< XLineColorItem const & >( 1736 rOldSet.Get(XATTR_LINECOLOR)).GetColorValue(); 1737 nLineThick = WW8ITEMVALUE(rOldSet, XATTR_LINEWIDTH, XLineWidthItem); 1738 1739 if( !nLineThick ) 1740 nLineThick = 15; // WW-default: 0.75 pt 1741 1742 nOutside = MatchSdrBoxIntoFlyBoxItem(aLineColor, eLineStyle, 1743 eShapeType, nLineThick, aBox); 1744 } 1745 1746 rInnerDist.Left()+=nLineThick; 1747 rInnerDist.Top()+=nLineThick; 1748 rInnerDist.Right()+=nLineThick; 1749 rInnerDist.Bottom()+=nLineThick; 1750 1751 const SvxBorderLine *pLine; 1752 if (0 != (pLine = aBox.GetLine(BOX_LINE_LEFT))) 1753 { 1754 rInnerDist.Left() -= (pLine->GetOutWidth() + pLine->GetInWidth() + 1755 pLine->GetDistance()); 1756 } 1757 1758 if (0 != (pLine = aBox.GetLine(BOX_LINE_TOP))) 1759 { 1760 rInnerDist.Top() -= (pLine->GetOutWidth() + pLine->GetInWidth() + 1761 pLine->GetDistance()); 1762 } 1763 1764 if (0 != (pLine = aBox.GetLine(BOX_LINE_RIGHT))) 1765 { 1766 rInnerDist.Right() -= (pLine->GetOutWidth() + pLine->GetInWidth() + 1767 pLine->GetDistance()); 1768 } 1769 1770 if (0 != (pLine = aBox.GetLine(BOX_LINE_BOTTOM))) 1771 { 1772 rInnerDist.Bottom() -= (pLine->GetOutWidth() + pLine->GetInWidth() + 1773 pLine->GetDistance()); 1774 } 1775 1776 // set distances from box's border to text contained within the box 1777 if( 0 < rInnerDist.Left() ) 1778 aBox.SetDistance( (sal_uInt16)rInnerDist.Left(), BOX_LINE_LEFT ); 1779 if( 0 < rInnerDist.Top() ) 1780 aBox.SetDistance( (sal_uInt16)rInnerDist.Top(), BOX_LINE_TOP ); 1781 if( 0 < rInnerDist.Right() ) 1782 aBox.SetDistance( (sal_uInt16)rInnerDist.Right(), BOX_LINE_RIGHT ); 1783 if( 0 < rInnerDist.Bottom() ) 1784 aBox.SetDistance( (sal_uInt16)rInnerDist.Bottom(), BOX_LINE_BOTTOM ); 1785 1786 bool bFixSize = !(WW8ITEMVALUE(rOldSet, SDRATTR_TEXT_AUTOGROWHEIGHT, 1787 SdrTextAutoGrowHeightItem)); 1788 1789 // Size: SwFmtFrmSize 1790 if( SFX_ITEM_SET != rFlySet.GetItemState(RES_FRM_SIZE, false) ) 1791 { 1792 const Rectangle& rSnapRect = pSdrObj->GetSnapRect(); 1793 // if necessary adapt width and position of the framework: The 1794 // recorded interior is to remain equally large despite thick edges. 1795 rFlySet.Put( SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE, 1796 rSnapRect.GetWidth() + 2*nOutside, 1797 rSnapRect.GetHeight() + 2*nOutside) ); 1798 } 1799 else //If a size is set, adjust it to consider border thickness 1800 { 1801 SwFmtFrmSize aSize = (const SwFmtFrmSize &)(rFlySet.Get(RES_FRM_SIZE)); 1802 1803 SwFmtFrmSize aNewSize = SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE, 1804 aSize.GetWidth() + 2*nOutside, 1805 aSize.GetHeight() + 2*nOutside); 1806 aNewSize.SetWidthSizeType(aSize.GetWidthSizeType()); 1807 rFlySet.Put( aNewSize ); 1808 } 1809 1810 //Sadly word puts escher borders outside the graphic, but orients the 1811 //graphic in relation to the top left inside the border. We don't 1812 if (nOutside) 1813 { 1814 SwFmtHoriOrient aHori = (const SwFmtHoriOrient &)(rFlySet.Get( 1815 RES_HORI_ORIENT)); 1816 aHori.SetPos(MakeSafePositioningValue(aHori.GetPos()-nOutside)); 1817 rFlySet.Put(aHori); 1818 1819 SwFmtVertOrient aVert = (const SwFmtVertOrient &)(rFlySet.Get( 1820 RES_VERT_ORIENT)); 1821 aVert.SetPos(aVert.GetPos()-nOutside); 1822 rFlySet.Put(aVert); 1823 } 1824 1825 // jetzt die Umrandung setzen 1826 rFlySet.Put( aBox ); 1827 1828 // Schattenwurf der Box: SvxShadowItem 1829 if( WW8ITEMVALUE(rOldSet, SDRATTR_SHADOW, SdrShadowItem) ) 1830 { 1831 SvxShadowItem aShadow( RES_SHADOW ); 1832 1833 const Color aShdColor = static_cast< SdrShadowColorItem const & >( 1834 rOldSet.Get(SDRATTR_SHADOWCOLOR)).GetColorValue(); 1835 const sal_Int32 nShdDistX = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWXDIST, 1836 SdrShadowXDistItem); 1837 const sal_Int32 nShdDistY = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWYDIST, 1838 SdrShadowYDistItem); 1839 //const sal_uInt16 nShdTrans= WW8ITEMVALUE(rOldSet, 1840 // SDRATTR_SHADOWTRANSPARENCE, SdrShadowTransparenceItem); 1841 1842 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1843 // 1844 // SfxVoidItem( SDRATTR_SHADOW3D ) 1845 // SfxVoidItem( SDRATTR_SHADOWPERSP ) 1846 1847 aShadow.SetColor( Color( aShdColor ) ); 1848 1849 aShadow.SetWidth(writer_cast<sal_uInt16>((Abs( nShdDistX) + 1850 Abs( nShdDistY )) / 2 )); 1851 1852 SvxShadowLocation eShdPosi; 1853 if( 0 <= nShdDistX ) 1854 { 1855 if( 0 <= nShdDistY ) 1856 eShdPosi = SVX_SHADOW_BOTTOMRIGHT; 1857 else 1858 eShdPosi = SVX_SHADOW_TOPRIGHT; 1859 } 1860 else 1861 { 1862 if( 0 <= nShdDistY ) 1863 eShdPosi = SVX_SHADOW_BOTTOMLEFT; 1864 else 1865 eShdPosi = SVX_SHADOW_TOPLEFT; 1866 } 1867 aShadow.SetLocation( eShdPosi ); 1868 1869 rFlySet.Put( aShadow ); 1870 } 1871 Color Temp(COL_WHITE); 1872 SvxBrushItem aBrushItem(Temp, RES_BACKGROUND); 1873 bool bBrushItemOk = false; 1874 sal_uInt8 nTrans = 0; 1875 1876 //Seperate transparency 1877 eState = rOldSet.GetItemState(XATTR_FILLTRANSPARENCE, true, &pItem); 1878 if (eState == SFX_ITEM_SET) 1879 { 1880 sal_uInt16 nRes = WW8ITEMVALUE(rOldSet, XATTR_FILLTRANSPARENCE, 1881 XFillTransparenceItem); 1882 nTrans = sal_uInt8((nRes * 0xFE) / 100); 1883 aBrushItem.GetColor().SetTransparency(nTrans); 1884 bBrushItemOk = true; 1885 } 1886 1887 // Hintergrund: SvxBrushItem 1888 eState = rOldSet.GetItemState(XATTR_FILLSTYLE, true, &pItem); 1889 if (eState == SFX_ITEM_SET) 1890 { 1891 const XFillStyle eFill = ((const XFillStyleItem*)pItem)->GetValue(); 1892 1893 switch (eFill) 1894 { 1895 case XFILL_NONE: 1896 //Writer graphics don't have it yet 1897 if (eShapeType != mso_sptPictureFrame) 1898 { 1899 aBrushItem.GetColor().SetTransparency(0xFE); 1900 bBrushItemOk = true; 1901 } 1902 break; 1903 case XFILL_SOLID: 1904 { 1905 const Color aColor = static_cast< XFillColorItem const & >( 1906 rOldSet.Get(XATTR_FILLCOLOR)).GetColorValue(); 1907 aBrushItem.SetColor(aColor); 1908 1909 if (bBrushItemOk) //has trans 1910 aBrushItem.GetColor().SetTransparency(nTrans); 1911 1912 bBrushItemOk = true; 1913 } 1914 break; 1915 case XFILL_GRADIENT: 1916 break; 1917 case XFILL_HATCH: 1918 break; 1919 case XFILL_BITMAP: 1920 { 1921 const Graphic aGraphic( 1922 static_cast< XFillBitmapItem const & >( 1923 rOldSet.Get(XATTR_FILLBITMAP)). 1924 GetBitmapValue().GetBitmap()); 1925 bool bTile = WW8ITEMVALUE(rOldSet, XATTR_FILLBMP_TILE, 1926 SfxBoolItem) ? true: false; 1927 GraphicObject aGrfObj(aGraphic); 1928 1929 aBrushItem.SetGraphicObject(aGrfObj); 1930 1931 if (bBrushItemOk) //has trans 1932 { 1933 GraphicObject *pGraphicObject = 1934 const_cast<GraphicObject *> 1935 (aBrushItem.GetGraphicObject()); 1936 GraphicAttr aAttr(pGraphicObject->GetAttr()); 1937 aAttr.SetTransparency(nTrans); 1938 pGraphicObject->SetAttr(aAttr); 1939 } 1940 1941 aBrushItem.SetGraphicPos(bTile ? GPOS_TILED : GPOS_AREA); 1942 1943 bBrushItemOk = true; 1944 } 1945 break; 1946 } 1947 } 1948 1949 if (bBrushItemOk) 1950 rFlySet.Put(aBrushItem, RES_BACKGROUND); 1951 } 1952 1953 void SwWW8ImplReader::AdjustLRWrapForWordMargins( 1954 const SvxMSDffImportRec &rRecord, SvxLRSpaceItem &rLR) 1955 { 1956 // Left adjustments - if horizontally aligned to left of 1957 // margin or column then remove the left wrapping 1958 if (rRecord.nXAlign == 1) 1959 { 1960 if ((rRecord.nXRelTo == 0) || (rRecord.nXRelTo == 2)) 1961 rLR.SetLeft((sal_uInt16)0); 1962 } 1963 1964 // Right adjustments - if horizontally aligned to right of 1965 // margin or column then remove the right wrapping 1966 if (rRecord.nXAlign == 3) 1967 { 1968 if ((rRecord.nXRelTo == 0) || (rRecord.nXRelTo == 2)) 1969 rLR.SetRight((sal_uInt16)0); 1970 } 1971 1972 //Inside margin, remove left wrapping 1973 if ((rRecord.nXAlign == 4) && (rRecord.nXRelTo == 0)) 1974 { 1975 rLR.SetLeft((sal_uInt16)0); 1976 } 1977 1978 //Outside margin, remove left wrapping 1979 if ((rRecord.nXAlign == 5) && (rRecord.nXRelTo == 0)) 1980 { 1981 rLR.SetRight((sal_uInt16)0); 1982 } 1983 } 1984 1985 1986 void SwWW8ImplReader::AdjustULWrapForWordMargins( 1987 const SvxMSDffImportRec &rRecord, SvxULSpaceItem &rUL) 1988 { 1989 // Top adjustment - remove upper wrapping if aligned to page 1990 // printable area or to page 1991 if (rRecord.nYAlign == 1) 1992 { 1993 if ((rRecord.nYRelTo == 0) || (rRecord.nYRelTo == 1)) 1994 rUL.SetUpper((sal_uInt16)0); 1995 } 1996 1997 // Bottom adjustment - remove bottom wrapping if aligned to page or 1998 // printable area or to page 1999 if (rRecord.nYAlign == 3) 2000 { 2001 if ((rRecord.nYRelTo == 0) || (rRecord.nYRelTo == 1)) 2002 rUL.SetLower((sal_uInt16)0); 2003 } 2004 2005 //Remove top margin if aligned vertically inside margin 2006 if ((rRecord.nYAlign == 4) && (rRecord.nYRelTo == 0)) 2007 rUL.SetUpper((sal_uInt16)0); 2008 2009 /* 2010 // Something like this needs to be done once inside and outside are 2011 // fixed 2012 if (rRecord.nYAlign == 4) 2013 { 2014 if (rRecord.nYRelTo == 0) 2015 rUL.SetUpper((sal_uInt16)0); 2016 } 2017 */ 2018 } 2019 2020 void SwWW8ImplReader::MapWrapIntoFlyFmt(SvxMSDffImportRec* pRecord, 2021 SwFrmFmt* pFlyFmt) 2022 { 2023 if (!pRecord || !pFlyFmt) 2024 return; 2025 2026 if (pRecord->nDxWrapDistLeft || pRecord->nDxWrapDistRight) 2027 { 2028 SvxLRSpaceItem aLR(writer_cast<sal_uInt16>(pRecord->nDxWrapDistLeft), 2029 writer_cast<sal_uInt16>(pRecord->nDxWrapDistRight), 0, 0, RES_LR_SPACE); 2030 AdjustLRWrapForWordMargins(*pRecord, aLR); 2031 pFlyFmt->SetFmtAttr(aLR); 2032 } 2033 if (pRecord->nDyWrapDistTop || pRecord->nDyWrapDistBottom) 2034 { 2035 SvxULSpaceItem aUL(writer_cast<sal_uInt16>(pRecord->nDyWrapDistTop), 2036 writer_cast<sal_uInt16>(pRecord->nDyWrapDistBottom), RES_UL_SPACE); 2037 AdjustULWrapForWordMargins(*pRecord, aUL); 2038 pFlyFmt->SetFmtAttr(aUL); 2039 } 2040 2041 //If we are contoured and have a custom polygon... 2042 if (pRecord->pWrapPolygon && pFlyFmt->GetSurround().IsContour()) 2043 { 2044 if (SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(*pFlyFmt)) 2045 { 2046 2047 /* 2048 Gather round children and hear of a tale that will raise the 2049 hairs on the back of your neck this dark halloween night. 2050 2051 There is a polygon in word that describes the wraping around 2052 the graphic. 2053 2054 Here are some sample values for the simplest case of a square 2055 around some solid coloured graphics 2056 2057 X Y Pixel size of graphic 2058 TopLeft -54 21600 400x400 2059 Bottom Right 0 21546 2060 2061 TopLeft -108 21600 200x200 2062 Bottom Right 0 21492 2063 2064 TopLeft -216 21600 100x100 2065 Bottom Right 0 21384 2066 2067 TopLeft -432 21600 50x50 2068 Bottom Right 0 21168 2069 2070 TopLeft -76 21600 283x212 2071 Bottom Right 0 21498 2072 2073 So given that the size of the values remains pretty much the 2074 same despite the size of the graphic, we can tell that the 2075 polygon is measured in units that are independant of the 2076 graphic. But why does the left corner move a different value 2077 to the left each time, and why does the bottom move upwards 2078 each time, when the right and top remain at the same value ? 2079 2080 I have no idea, but clearly once we calculate the values out 2081 we see that the left margin is always a fixed realworld 2082 distance from the true left and the polygon bottom is the same 2083 fixed value from the bottom. i.e. 15twips. 2084 2085 So here we take our word provided polygon, shift it to the 2086 right by 15twips and rescale it widthwise to shrink the width 2087 a little to fit the now moved right margin back to where it 2088 was, and stretch the height a little to make the bottom move 2089 down the missing 15twips then we get a polygon that matches 2090 what I actually see in word 2091 */ 2092 2093 PolyPolygon aPoly(*pRecord->pWrapPolygon); 2094 const Size &rSize = pNd->GetTwipSize(); 2095 /* 2096 Move to the left by 15twips, and rescale to 2097 a) shrink right bound back to orig position 2098 b) stretch bottom bound to where I think it should have been 2099 in the first place 2100 */ 2101 Fraction aMoveHack(ww::nWrap100Percent, rSize.Width()); 2102 aMoveHack *= Fraction(15, 1); 2103 long nMove(aMoveHack); 2104 aPoly.Move(nMove, 0); 2105 2106 Fraction aHackX(ww::nWrap100Percent, ww::nWrap100Percent + nMove); 2107 Fraction aHackY(ww::nWrap100Percent, ww::nWrap100Percent - nMove); 2108 aPoly.Scale(aHackX, aHackY); 2109 2110 //Turn polygon back into units that match the graphic's 2111 const Size &rOrigSize = pNd->GetGraphic().GetPrefSize(); 2112 Fraction aMapPolyX(rOrigSize.Width(), ww::nWrap100Percent); 2113 Fraction aMapPolyY(rOrigSize.Height(), ww::nWrap100Percent); 2114 aPoly.Scale(aMapPolyX, aMapPolyY); 2115 2116 // --> OD 2005-05-19 #i47277# - contour is already in unit of the 2117 // graphic prefered unit. Thus, call method <SetContour(..)> 2118 pNd->SetContour(&aPoly); 2119 // <-- 2120 } 2121 } 2122 } 2123 2124 void SwWW8ImplReader::SetAttributesAtGrfNode( SvxMSDffImportRec* pRecord, 2125 SwFrmFmt *pFlyFmt, WW8_FSPA *pF ) 2126 { 2127 const SwNodeIndex* pIdx = pFlyFmt->GetCntnt(false).GetCntntIdx(); 2128 SwGrfNode* pGrfNd; 2129 if( pIdx && 0 != (pGrfNd = rDoc.GetNodes()[pIdx->GetIndex() + 1]->GetGrfNode() )) 2130 { 2131 Size aSz(pGrfNd->GetTwipSize()); 2132 // --> OD 2005-08-01 #124722# - use type <sal_uInt64> instead of <sal_uLong> 2133 // to get correct results in the following calculations. 2134 sal_uInt64 rHeight = aSz.Height(); 2135 sal_uInt64 rWidth = aSz.Width(); 2136 // <-- 2137 if( !rWidth && pF) 2138 rWidth = pF->nXaRight - pF->nXaLeft; 2139 else if( !rHeight && pF) 2140 rHeight = pF->nYaBottom - pF->nYaTop; 2141 2142 if( pRecord->nCropFromTop || pRecord->nCropFromBottom || 2143 pRecord->nCropFromLeft || pRecord->nCropFromRight ) 2144 { 2145 SwCropGrf aCrop; // Cropping is stored in 'fixed floats' 2146 // 16.16 (it est fraction times total 2147 if( pRecord->nCropFromTop ) // image width or height resp.) 2148 aCrop.SetTop( static_cast< sal_Int32 >( 2149 ( ( (pRecord->nCropFromTop >> 16 ) * rHeight ) 2150 + (((pRecord->nCropFromTop & 0xffff) * rHeight ) >> 16) ))); 2151 if( pRecord->nCropFromBottom ) 2152 aCrop.SetBottom( static_cast< sal_Int32 >( 2153 ( ( (pRecord->nCropFromBottom >> 16 ) * rHeight ) 2154 + (((pRecord->nCropFromBottom & 0xffff) * rHeight ) >> 16) ))); 2155 if( pRecord->nCropFromLeft ) 2156 aCrop.SetLeft( static_cast< sal_Int32 >( 2157 ( ( (pRecord->nCropFromLeft >> 16 ) * rWidth ) 2158 + (((pRecord->nCropFromLeft & 0xffff) * rWidth ) >> 16) ))); 2159 if( pRecord->nCropFromRight ) 2160 aCrop.SetRight( static_cast< sal_Int32 >( 2161 ( ( (pRecord->nCropFromRight >> 16 ) * rWidth ) 2162 + (((pRecord->nCropFromRight & 0xffff) * rWidth ) >> 16) ))); 2163 2164 pGrfNd->SetAttr( aCrop ); 2165 } 2166 2167 if (pRecord && pRecord->pObj) 2168 { 2169 const SfxItemSet& rOldSet = pRecord->pObj->GetMergedItemSet(); 2170 //contrast 2171 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFCONTRAST, 2172 SdrGrafContrastItem)) 2173 { 2174 SwContrastGrf aContrast( 2175 WW8ITEMVALUE(rOldSet, 2176 SDRATTR_GRAFCONTRAST, SdrGrafContrastItem)); 2177 pGrfNd->SetAttr( aContrast ); 2178 } 2179 2180 //luminance 2181 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFLUMINANCE, 2182 SdrGrafLuminanceItem)) 2183 { 2184 SwLuminanceGrf aLuminance(WW8ITEMVALUE(rOldSet, 2185 SDRATTR_GRAFLUMINANCE, SdrGrafLuminanceItem)); 2186 pGrfNd->SetAttr( aLuminance ); 2187 } 2188 //gamma 2189 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA, SdrGrafGamma100Item)) 2190 { 2191 double fVal = WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA, 2192 SdrGrafGamma100Item); 2193 pGrfNd->SetAttr(SwGammaGrf(fVal/100.)); 2194 } 2195 2196 //drawmode 2197 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFMODE, SdrGrafModeItem)) 2198 { 2199 SwDrawModeGrf aDrawMode( static_cast< sal_uInt16 >(WW8ITEMVALUE(rOldSet, 2200 SDRATTR_GRAFMODE, SdrGrafModeItem)) ); 2201 pGrfNd->SetAttr( aDrawMode ); 2202 } 2203 } 2204 } 2205 } 2206 2207 SdrObject* SwWW8ImplReader::CreateContactObject(SwFrmFmt* pFlyFmt) 2208 { 2209 if (pFlyFmt) 2210 { 2211 //JP 11.1.2002: task 96329 2212 SdrObject* pNewObject = mbNewDoc ? 0 : pFlyFmt->FindRealSdrObject(); 2213 if (!pNewObject) 2214 pNewObject = pFlyFmt->FindSdrObject(); 2215 if (!pNewObject && pFlyFmt->ISA(SwFlyFrmFmt)) 2216 { 2217 SwFlyDrawContact* pContactObject 2218 = new SwFlyDrawContact(static_cast<SwFlyFrmFmt*>(pFlyFmt), 2219 pDrawModel); 2220 pNewObject = pContactObject->GetMaster(); 2221 } 2222 return pNewObject; 2223 } 2224 return 0; 2225 } 2226 2227 //#109311# Miserable miserable hack to fudge word's graphic layout in 2228 //RTL mode to ours. 2229 bool SwWW8ImplReader::MiserableRTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth, 2230 sal_Int16 eHoriOri, sal_Int16 eHoriRel) 2231 { 2232 if (!IsRightToLeft()) 2233 return false; 2234 return RTLGraphicsHack(rLeft, nWidth, eHoriOri, eHoriRel, 2235 maSectionManager.GetPageLeft(), 2236 maSectionManager.GetPageRight(), 2237 maSectionManager.GetPageWidth()); 2238 } 2239 2240 RndStdIds SwWW8ImplReader::ProcessEscherAlign(SvxMSDffImportRec* pRecord, 2241 WW8_FSPA *pFSPA, SfxItemSet &rFlySet, bool /*bOrgObjectWasReplace*/) 2242 { 2243 ASSERT(pRecord || pFSPA, "give me something! to work with for anchoring"); 2244 if (!pRecord && !pFSPA) 2245 return FLY_AT_PAGE; 2246 2247 SvxMSDffImportRec aRecordFromFSPA; 2248 if (!pRecord) 2249 { 2250 pRecord = &aRecordFromFSPA; 2251 pRecord->nXRelTo = pFSPA->nbx; 2252 pRecord->nYRelTo = pFSPA->nby; 2253 } 2254 2255 // nXAlign - abs. Position, Left, Centered, Right, Inside, Outside 2256 // nYAlign - abs. Position, Top, Centered, Bottom, Inside, Outside 2257 2258 // nXRelTo - Page printable area, Page, Column, Character 2259 // nYRelTo - Page printable area, Page, Paragraph, Line 2260 2261 const sal_uInt32 nCntXAlign = 6; 2262 const sal_uInt32 nCntYAlign = 6; 2263 2264 const sal_uInt32 nCntRelTo = 4; 2265 2266 sal_uInt32 nXAlign = nCntXAlign > pRecord->nXAlign ? pRecord->nXAlign : 1; 2267 sal_uInt32 nYAlign = nCntYAlign > pRecord->nYAlign ? pRecord->nYAlign : 1; 2268 2269 if (pFSPA) 2270 { 2271 /* 2272 #74188# #i15718# #i19008# 2273 Strangely in this case the FSPA value seems to be considered before 2274 the newer escher nXRelTo record. 2275 */ 2276 // --> OD 2005-08-04 #i52565# - correct condition checking: 2277 // first check, if <nXRelTo> and <nYRelTo> have default values. This 2278 // is a hint that these values aren't set by the escher import - see 2279 // method <SwMSDffManager::ProcessObj(..)>. Then, check if for each 2280 // values, if it differs from the one in the FSPA. 2281 if ( pRecord->nXRelTo == 2 && pRecord->nYRelTo == 2 ) 2282 { 2283 // if <nYRelTo> differs from <FSPA.nby> overwrite <nYRelTo> 2284 if ( pFSPA->nby != pRecord->nYRelTo ) 2285 { 2286 pRecord->nYRelTo = pFSPA->nby; 2287 } 2288 } 2289 // <-- 2290 } 2291 2292 sal_uInt32 nXRelTo = nCntRelTo > pRecord->nXRelTo ? pRecord->nXRelTo : 1; 2293 sal_uInt32 nYRelTo = nCntRelTo > pRecord->nYRelTo ? pRecord->nYRelTo : 1; 2294 2295 // --> OD 2005-03-03 #i43718# 2296 RndStdIds eAnchor = IsInlineEscherHack() ? FLY_AS_CHAR : FLY_AT_CHAR; 2297 // <-- 2298 2299 SwFmtAnchor aAnchor( eAnchor ); 2300 aAnchor.SetAnchor( pPaM->GetPoint() ); 2301 rFlySet.Put( aAnchor ); 2302 2303 if (pFSPA) 2304 { 2305 // OD 14.10.2003 #i18732# 2306 //Given new layout where everything is changed to be anchored to 2307 //character the following 4 tables may need to be changed. 2308 2309 // horizontal Adjustment 2310 static const sal_Int16 aHoriOriTab[ nCntXAlign ] = 2311 { 2312 text::HoriOrientation::NONE, // From left position 2313 text::HoriOrientation::LEFT, // left 2314 text::HoriOrientation::CENTER, // centered 2315 text::HoriOrientation::RIGHT, // right 2316 // --> OD 2004-12-06 #i36649# 2317 // - inside -> text::HoriOrientation::LEFT and outside -> text::HoriOrientation::RIGHT 2318 text::HoriOrientation::LEFT, // inside 2319 text::HoriOrientation::RIGHT // outside 2320 // <-- 2321 }; 2322 2323 2324 // generic vertical Adjustment 2325 static const sal_Int16 aVertOriTab[ nCntYAlign ] = 2326 { 2327 text::VertOrientation::NONE, // From Top position 2328 text::VertOrientation::TOP, // top 2329 text::VertOrientation::CENTER, // centered 2330 text::VertOrientation::BOTTOM, // bottom 2331 text::VertOrientation::LINE_TOP, // inside (obscure) 2332 text::VertOrientation::LINE_BOTTOM // outside (obscure) 2333 }; 2334 2335 // CMC,OD 24.11.2003 #i22673# - to-line vertical alignment 2336 static const sal_Int16 aToLineVertOriTab[ nCntYAlign ] = 2337 { 2338 text::VertOrientation::NONE, // below 2339 text::VertOrientation::LINE_BOTTOM, // top 2340 text::VertOrientation::LINE_CENTER, // centered 2341 text::VertOrientation::LINE_TOP, // bottom 2342 text::VertOrientation::LINE_BOTTOM, // inside (obscure) 2343 text::VertOrientation::LINE_TOP // outside (obscure) 2344 }; 2345 2346 // Adjustment is horizontally relative to... 2347 static const sal_Int16 aHoriRelOriTab[nCntRelTo] = 2348 { 2349 text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin 2350 text::RelOrientation::PAGE_FRAME, // 1 is page margin 2351 text::RelOrientation::FRAME, // 2 is relative to column 2352 text::RelOrientation::CHAR // 3 is relative to character 2353 }; 2354 2355 // Adjustment is vertically relative to... 2356 // CMC, OD 24.11.2003 #i22673# - adjustment for new vertical alignment 2357 // at top of line. 2358 static const sal_Int16 aVertRelOriTab[nCntRelTo] = 2359 { 2360 text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin 2361 text::RelOrientation::PAGE_FRAME, // 1 is page margin 2362 text::RelOrientation::FRAME, // 2 is relative to paragraph 2363 text::RelOrientation::TEXT_LINE // 3 is relative to line 2364 }; 2365 2366 sal_Int16 eHoriOri = aHoriOriTab[ nXAlign ]; 2367 sal_Int16 eHoriRel = aHoriRelOriTab[ nXRelTo ]; 2368 2369 // --> OD 2004-12-06 #i36649# - adjustments for certain alignments 2370 if ( eHoriOri == text::HoriOrientation::LEFT && eHoriRel == text::RelOrientation::PAGE_FRAME ) 2371 { 2372 // convert 'left to page' to 'from left -<width> to page text area' 2373 eHoriOri = text::HoriOrientation::NONE; 2374 eHoriRel = text::RelOrientation::PAGE_PRINT_AREA; 2375 const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft; 2376 pFSPA->nXaLeft = -nWidth; 2377 pFSPA->nXaRight = 0; 2378 } 2379 else if ( eHoriOri == text::HoriOrientation::RIGHT && eHoriRel == text::RelOrientation::PAGE_FRAME ) 2380 { 2381 // convert 'right to page' to 'from left 0 to right page border' 2382 eHoriOri = text::HoriOrientation::NONE; 2383 eHoriRel = text::RelOrientation::PAGE_RIGHT; 2384 const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft; 2385 pFSPA->nXaLeft = 0; 2386 pFSPA->nXaRight = nWidth; 2387 } 2388 // <-- 2389 2390 // --> OD 2005-02-07 #i24255# - position of floating screen objects in 2391 // R2L layout are given in L2R layout, thus convert them of all 2392 // floating screen objects, which are imported. 2393 { 2394 //#109311# Miserable miserable hack. 2395 SwTwips nWidth = (pFSPA->nXaRight - pFSPA->nXaLeft); 2396 SwTwips nLeft = pFSPA->nXaLeft; 2397 if (MiserableRTLGraphicsHack(nLeft, nWidth, eHoriOri, 2398 eHoriRel)) 2399 { 2400 pFSPA->nXaLeft = nLeft; 2401 pFSPA->nXaRight = pFSPA->nXaLeft + nWidth; 2402 } 2403 } 2404 // <-- 2405 2406 // --> OD 2005-01-20 #118546# - if the object is anchored inside 2407 // a table cell, is horizontal aligned at frame|character and 2408 // has wrap through, but its attribute 'layout in table cell' isn't set, 2409 // convert its horizontal alignment to page text area. 2410 // --> OD 2008-04-10 #i84783# - use new method <IsObjectLayoutInTableCell()> 2411 if ( nInTable && 2412 ( eHoriRel == text::RelOrientation::FRAME || eHoriRel == text::RelOrientation::CHAR ) && 2413 pFSPA->nwr == 3 && 2414 // pRecord->nLayoutInTableCell == 0x80000000 ) 2415 !IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell ) ) 2416 { 2417 eHoriRel = text::RelOrientation::PAGE_PRINT_AREA; 2418 } 2419 // <-- 2420 2421 SwFmtHoriOrient aHoriOri(MakeSafePositioningValue(pFSPA->nXaLeft), 2422 eHoriOri, eHoriRel); 2423 if( 4 <= nXAlign ) 2424 aHoriOri.SetPosToggle(true); 2425 rFlySet.Put( aHoriOri ); 2426 2427 //Writer honours this wrap distance when aligned as "left" or "right", 2428 //Word doesn't. Writer doesn't honour it when its "from left". 2429 if (eHoriOri == text::HoriOrientation::LEFT) 2430 pRecord->nDxWrapDistLeft=0; 2431 else if (eHoriOri == text::HoriOrientation::RIGHT) 2432 pRecord->nDxWrapDistRight=0; 2433 2434 sal_Int16 eVertRel; 2435 // OD 14.10.2003 #i18732# 2436 eVertRel = aVertRelOriTab[ nYRelTo ]; 2437 // CMC, OD 24.11.2003 #i22673# - fill <eVertOri> in dependence of <eVertRel> 2438 sal_Int16 eVertOri; 2439 if ( eVertRel == text::RelOrientation::TEXT_LINE ) 2440 { 2441 eVertOri = aToLineVertOriTab[ nYAlign ]; 2442 } 2443 else 2444 { 2445 eVertOri = aVertOriTab[ nYAlign ]; 2446 } 2447 2448 //Below line in word is a positive value, while in writer its 2449 //negative 2450 long nYPos = pFSPA->nYaTop; 2451 // CMC, OD 24.11.2003 #i22673# 2452 if ((eVertRel == text::RelOrientation::TEXT_LINE) && (eVertOri == text::VertOrientation::NONE)) 2453 nYPos = -nYPos; 2454 2455 rFlySet.Put(SwFmtVertOrient(MakeSafePositioningValue(nYPos), 2456 eVertOri, eVertRel)); 2457 2458 if ( 2459 (pFSPA->nYaTop < 0) && (eVertOri == text::VertOrientation::NONE) && 2460 ((eAnchor == FLY_AT_PARA) || (eAnchor == FLY_AT_CHAR)) 2461 ) 2462 { 2463 maTracer.Log(sw::log::eNegativeVertPlacement); 2464 } 2465 } 2466 2467 return eAnchor; 2468 } 2469 2470 // --> OD 2008-04-10 #i84783# 2471 bool SwWW8ImplReader::IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTableCell ) const 2472 { 2473 bool bIsObjectLayoutInTableCell = false; 2474 2475 if ( bVer8 ) 2476 { 2477 const sal_uInt16 nWWVersion = pWwFib->nProduct & 0xE000; 2478 switch ( nWWVersion ) 2479 { 2480 case 0x0000: // version 8 aka Microsoft Word 97 2481 { 2482 bIsObjectLayoutInTableCell = false; 2483 ASSERT( nLayoutInTableCell == 0xFFFFFFFF, 2484 "no explicit object attribute layout in table cell excepted." ); 2485 } 2486 break; 2487 case 0x2000: // version 9 aka Microsoft Word 2000 2488 case 0x4000: // version 10 aka Microsoft Word 2002 2489 case 0x6000: // version 11 aka Microsoft Word 2003 2490 case 0x8000: // version 12 aka Microsoft Word 2007 2491 { 2492 // --> OD 2009-01-13 #i98037# 2493 // adjustment of conditions needed after deeper analysis of 2494 // certain test cases. 2495 if ( nLayoutInTableCell == 0xFFFFFFFF || // no explicit attribute value given 2496 nLayoutInTableCell & 0x80008000 || 2497 ( nLayoutInTableCell & 0x02000000 && 2498 !(nLayoutInTableCell & 0x80000000 ) ) ) 2499 // <-- 2500 { 2501 bIsObjectLayoutInTableCell = true; 2502 } 2503 else 2504 { 2505 bIsObjectLayoutInTableCell = false; 2506 } 2507 } 2508 break; 2509 default: 2510 { 2511 ASSERT( false, 2512 "unknown version." ); 2513 } 2514 } 2515 } 2516 2517 return bIsObjectLayoutInTableCell; 2518 } 2519 // <-- 2520 2521 SwFrmFmt* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp ) 2522 { 2523 if( nIniFlags & WW8FL_NO_GRAFLAYER ) 2524 return 0; 2525 2526 ::SetProgressState(nProgress, mpDocShell); // Update 2527 2528 nDrawCpO = pWwFib->GetBaseCp(pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX); 2529 2530 GrafikCtor(); 2531 2532 WW8PLCFspecial* pPF = pPlcxMan->GetFdoa(); 2533 if( !pPF ) 2534 { 2535 ASSERT( !this, "Where is the grapic (1) ?" ); 2536 return 0; 2537 } 2538 2539 if( bVer67 ) 2540 { 2541 long nOldPos = pStrm->Tell(); 2542 2543 nDrawXOfs = nDrawYOfs = 0; 2544 ReadGrafLayer1( pPF, nGrafAnchorCp ); 2545 2546 pStrm->Seek( nOldPos ); 2547 return 0; 2548 } 2549 2550 //Normal case of Word 8+ version stuff 2551 pPF->SeekPos( nGrafAnchorCp ); 2552 2553 WW8_FC nStartFc; 2554 void* pF0; 2555 if( !pPF->Get( nStartFc, pF0 ) ){ 2556 ASSERT( !this, "+Wo ist die Grafik (2) ?" ); 2557 return 0; 2558 } 2559 2560 WW8_FSPA_SHADOW* pFS = (WW8_FSPA_SHADOW*)pF0; 2561 WW8_FSPA* pF; 2562 #ifdef __WW8_NEEDS_COPY 2563 WW8_FSPA aFSFA; 2564 pF = &aFSFA; 2565 WW8FSPAShadowToReal( pFS, pF ); 2566 #else 2567 pF = (WW8_FSPA*)pFS; 2568 #endif // defined __WW8_NEEDS_COPY 2569 if( !pF->nSpId ) 2570 { 2571 ASSERT( !this, "+Wo ist die Grafik (3) ?" ); 2572 return 0; 2573 } 2574 2575 if (!pMSDffManager->GetModel()) 2576 pMSDffManager->SetModel(pDrawModel, 1440); 2577 2578 2579 Rectangle aRect(pF->nXaLeft, pF->nYaTop, pF->nXaRight, pF->nYaBottom); 2580 SvxMSDffImportData aData( aRect ); 2581 2582 /* 2583 #i20540# 2584 The SdrOle2Obj will try and manage any ole objects it finds, causing all 2585 sorts of trouble later on 2586 */ 2587 SwDocShell* pPersist = rDoc.GetDocShell(); 2588 rDoc.SetDocShell(0); //#i20540# Persist guard 2589 2590 SdrObject* pObject = 0; 2591 bool bOk = (pMSDffManager->GetShape(pF->nSpId, pObject, aData) && pObject); 2592 2593 rDoc.SetDocShell(pPersist); //#i20540# Persist guard 2594 2595 if (!bOk) 2596 { 2597 ASSERT( !this, "Where is the Shape ?" ); 2598 return 0; 2599 } 2600 2601 bool bDone = false; 2602 SdrObject* pOurNewObject = 0; 2603 bool bReplaceable = false; 2604 2605 switch (SdrObjKind(pObject->GetObjIdentifier())) 2606 { 2607 case OBJ_GRAF: 2608 bReplaceable = true; 2609 bDone = true; 2610 break; 2611 case OBJ_OLE2: 2612 bReplaceable = true; 2613 break; 2614 default: 2615 break; 2616 2617 } 2618 2619 // OD 14.10.2003 - keep wrapping of objects in page header/footer. 2620 /* 2621 //#108778# when in a header or footer word appears to treat all elements 2622 //are wrap through 2623 if (bIsHeader || bIsFooter) 2624 pF->nwr = 3; 2625 */ 2626 2627 // Umfluss-Modus ermitteln 2628 SfxItemSet aFlySet(rDoc.GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1); 2629 SwSurround eSurround = SURROUND_PARALLEL; 2630 bool bContour = false; 2631 switch (pF->nwr) 2632 { 2633 case 0: //0 like 2, but doesn't require absolute object 2634 case 2: //2 wrap around absolute object 2635 eSurround = SURROUND_PARALLEL; 2636 break; 2637 case 1: //1 no text next to shape 2638 eSurround = SURROUND_NONE; 2639 break; 2640 case 3: //3 wrap as if no object present 2641 eSurround = SURROUND_THROUGHT; 2642 break; 2643 case 4: //4 wrap tightly around object 2644 case 5: //5 wrap tightly, but allow holes 2645 eSurround = SURROUND_PARALLEL; 2646 bContour = true; 2647 break; 2648 } 2649 2650 // bei Modus 2 oder 4 auch den Zusatzparameter beruecksichtigen 2651 if ( (2 == pF->nwr) || (4 == pF->nwr) ) 2652 { 2653 switch( pF->nwrk ) 2654 { 2655 //0 wrap both sides 2656 case 0: 2657 eSurround = SURROUND_PARALLEL; 2658 break; 2659 //1 wrap only on left 2660 case 1: 2661 eSurround = SURROUND_LEFT; 2662 break; 2663 //2 wrap only on right 2664 case 2: 2665 eSurround = SURROUND_RIGHT; 2666 break; 2667 //3 wrap only on largest side 2668 case 3: 2669 eSurround = SURROUND_IDEAL; 2670 break; 2671 } 2672 } 2673 2674 SwFmtSurround aSur( eSurround ); 2675 aSur.SetContour( bContour ); 2676 aSur.SetOutside(true); // Winword kann nur Aussen-Konturen 2677 aFlySet.Put( aSur ); 2678 2679 // eingelesenes Objekt (kann eine ganze Gruppe sein) jetzt korrekt 2680 // positionieren usw. 2681 2682 ASSERT(!((aData.GetRecCount() != 1) && bReplaceable), 2683 "Replaceable drawing with > 1 entries ?"); 2684 2685 if (aData.GetRecCount() != 1) 2686 bReplaceable = false; 2687 2688 SvxMSDffImportRec* pRecord = 0; 2689 /* 2690 Get the record for top level object, so we can get the word anchoring 2691 and wrapping information for it. 2692 */ 2693 sal_uInt16 nRecCount = aData.GetRecCount(); 2694 for (sal_uInt16 nTxbx=0; nTxbx < nRecCount; ++nTxbx ) 2695 { 2696 pRecord = aData.GetRecord( nTxbx ); 2697 if (pRecord && pRecord->pObj == pObject) 2698 break; 2699 else 2700 pRecord = 0; 2701 } 2702 2703 ASSERT(pRecord, "how did that happen?"); 2704 if (!pRecord) 2705 return 0; 2706 2707 // --> OD 2008-04-10 #i84783# 2708 // //cmc: We're in a table, and the element has the magic Word XP bit set 2709 // //to enable layout inside a cell 2710 // // --> OD 2005-08-10 #124714# - undo change made for issue #i33442# 2711 // bool bLayoutInTableCell = ( nInTable && 2712 // pRecord->nLayoutInTableCell & 0x00008000 ); 2713 // // <-- 2714 const bool bLayoutInTableCell = 2715 nInTable && IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell ); 2716 // <-- 2717 2718 // OD 14.10.2003 #i18732# 2719 // Switch on 'follow text flow', 2720 // if object is laid out inside table cell and 2721 // its wrapping isn't 'SURROUND_THROUGH' 2722 if (bLayoutInTableCell && eSurround != SURROUND_THROUGHT) 2723 { 2724 SwFmtFollowTextFlow aFollowTextFlow( sal_True ); 2725 aFlySet.Put( aFollowTextFlow ); 2726 } 2727 2728 2729 //#i21847# 2730 //Some shapes are set to *hidden*, don't import those ones. 2731 if (pRecord->bHidden) 2732 return 0; 2733 2734 // If we are to be "below text" then we are not to be opaque 2735 // #i14045# MM If we are in a header or footer then make the object transparent 2736 // Not exactly like word but close enough for now 2737 2738 // --> OD 2005-03-07 #b6234902# - both flags <bBelowText> and <bDrawHell> 2739 // have to be set to move object into the background. 2740 // --> OD 2005-04-11 #i46794# - it reveals that value of flag <bBelowText> 2741 // can be neglected. 2742 const bool bMoveToBackgrd = pRecord->bDrawHell || 2743 ( ( bIsHeader || bIsFooter ) && pF->nwr == 3 ); 2744 if ( bMoveToBackgrd ) 2745 aFlySet.Put(SvxOpaqueItem(RES_OPAQUE,false)); 2746 2747 String aObjName = pObject->GetName(); 2748 2749 SwFrmFmt* pRetFrmFmt = 0; 2750 if (bReplaceable) 2751 { 2752 //Single graphics or ole objects 2753 pRetFrmFmt = ImportReplaceableDrawables(pObject, pOurNewObject, pRecord, 2754 pF, aFlySet); 2755 } 2756 else 2757 { 2758 //Drawing objects, (e.g. ovals or drawing groups) 2759 if (pF->bRcaSimple) 2760 { 2761 pF->nbx = WW8_FSPA::RelPageBorder; 2762 pF->nby = WW8_FSPA::RelPageBorder; 2763 } 2764 2765 RndStdIds eAnchor = ProcessEscherAlign(pRecord, pF, aFlySet, 2766 bReplaceable); 2767 2768 // Should we, and is it possible to make this into a writer textbox 2769 if ((!(nIniFlags1 & WW8FL_NO_FLY_FOR_TXBX)) && pRecord->bReplaceByFly) 2770 { 2771 pRetFrmFmt = ConvertDrawTextToFly(pObject, pOurNewObject, pRecord, 2772 eAnchor, pF, aFlySet); 2773 if (pRetFrmFmt) 2774 bDone = true; 2775 } 2776 2777 if (!bDone) 2778 { 2779 sw::util::SetLayer aSetLayer(rDoc); 2780 if ( bMoveToBackgrd ) 2781 aSetLayer.SendObjectToHell(*pObject); 2782 else 2783 aSetLayer.SendObjectToHeaven(*pObject); 2784 2785 if (!IsInlineEscherHack()) 2786 { 2787 /* 2788 #97824# Need to make sure that the correct layer ordering is 2789 applied. 2790 */ 2791 // --> OD 2004-12-13 #117915# - pass information, if object 2792 // is in page header|footer to method. 2793 pWWZOrder->InsertEscherObject( pObject, pF->nSpId, 2794 bIsHeader || bIsFooter ); 2795 // <-- 2796 } 2797 else 2798 { 2799 pWWZOrder->InsertTextLayerObject(pObject); 2800 } 2801 2802 pRetFrmFmt = rDoc.Insert(*pPaM, *pObject, &aFlySet, NULL); 2803 2804 ASSERT(pRetFrmFmt->GetAnchor().GetAnchorId() == 2805 eAnchor, "Not the anchor type requested!"); 2806 2807 /* 2808 Insert text if necessary into textboxes contained in groups. 2809 */ 2810 if (aData.HasRecords()) 2811 { 2812 sal_uInt16 nCount = aData.GetRecCount(); 2813 for (sal_uInt16 nTxbx=0; nTxbx < nCount; ++nTxbx) 2814 { 2815 pRecord = aData.GetRecord(nTxbx); 2816 if (pRecord && pRecord->pObj && pRecord->aTextId.nTxBxS) 2817 { // #i52825# pRetFrmFmt can be NULL 2818 pRetFrmFmt = MungeTextIntoDrawBox(pRecord->pObj, 2819 pRecord, nGrafAnchorCp, pRetFrmFmt); 2820 } 2821 } 2822 } 2823 } 2824 } 2825 2826 // --> OD 2005-03-11 #i44344#, #i44681# - positioning attributes already set 2827 if ( pRetFrmFmt /*#i52825# */ && pRetFrmFmt->ISA(SwDrawFrmFmt) ) 2828 { 2829 static_cast<SwDrawFrmFmt*>(pRetFrmFmt)->PosAttrSet(); 2830 } 2831 // <-- 2832 if (!IsInlineEscherHack()) 2833 MapWrapIntoFlyFmt(pRecord, pRetFrmFmt); 2834 2835 // Set frame name with object name 2836 if( aObjName.Len() ) 2837 pRetFrmFmt->SetName( aObjName ); 2838 return AddAutoAnchor(pRetFrmFmt); 2839 } 2840 2841 SwFrmFmt *SwWW8ImplReader::AddAutoAnchor(SwFrmFmt *pFmt) 2842 { 2843 if (pFmt && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR)) 2844 { 2845 sal_uInt16 nTextAreaWidth = static_cast< sal_uInt16 >( maSectionManager.GetPageWidth() - 2846 maSectionManager.GetPageRight() - maSectionManager.GetPageLeft()); 2847 2848 if (pFmt->GetFrmSize().GetSize().Width() > nTextAreaWidth) 2849 maTracer.Log(sw::log::eTooWideAsChar); 2850 } 2851 2852 /* 2853 * anchored to character at the current position will move along the 2854 * paragraph as text is added because we are at the insertion point. 2855 * 2856 * Leave to later and set the correct location then. 2857 */ 2858 if ((pFmt) && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR)) 2859 { 2860 pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFmt); 2861 } 2862 return pFmt; 2863 } 2864 2865 SwFrmFmt* SwWW8ImplReader::MungeTextIntoDrawBox(SdrObject* pTrueObject, 2866 SvxMSDffImportRec *pRecord, long nGrafAnchorCp, SwFrmFmt* pRetFrmFmt) 2867 { 2868 SdrTextObj* pSdrTextObj; 2869 2870 // Pruefen, ob Gruppenobjekt (z.B. zwei Klammern) vorliegt 2871 if (SdrObjGroup* pThisGroup = PTR_CAST(SdrObjGroup, pRecord->pObj)) 2872 { 2873 // Gruppenobjekte haben keinen Text. Fuege ein Textobjekt in die 2874 // Gruppe ein, um den Text zu halten. 2875 pSdrTextObj = new SdrRectObj( OBJ_TEXT, pThisGroup->GetCurrentBoundRect()); 2876 2877 SfxItemSet aSet(pDrawModel->GetItemPool()); 2878 aSet.Put(XFillStyleItem(XFILL_NONE)); 2879 aSet.Put(XLineStyleItem(XLINE_NONE)); 2880 aSet.Put(SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE )); 2881 aSet.Put(SdrTextAutoGrowHeightItem(false)); 2882 aSet.Put(SdrTextAutoGrowWidthItem(false)); 2883 pSdrTextObj->SetMergedItemSet(aSet); 2884 2885 long nAngle = pRecord->nTextRotationAngle; 2886 if ( nAngle ) 2887 { 2888 double a = nAngle*nPi180; 2889 pSdrTextObj->NbcRotate(pSdrTextObj->GetCurrentBoundRect().Center(), nAngle, 2890 sin(a), cos(a) ); 2891 } 2892 2893 pSdrTextObj->NbcSetLayer( pThisGroup->GetLayer() ); 2894 pThisGroup->GetSubList()->NbcInsertObject(pSdrTextObj); 2895 } 2896 else 2897 pSdrTextObj = PTR_CAST(SdrTextObj, pRecord->pObj); 2898 2899 if( pSdrTextObj ) 2900 { 2901 Size aObjSize(pSdrTextObj->GetSnapRect().GetWidth(), 2902 pSdrTextObj->GetSnapRect().GetHeight()); 2903 2904 // Objekt ist Bestandteil einer Gruppe? 2905 SdrObject* pGroupObject = pSdrTextObj->GetUpGroup(); 2906 2907 sal_uInt32 nOrdNum = pSdrTextObj->GetOrdNum(); 2908 bool bEraseThisObject; 2909 InsertTxbxText( pSdrTextObj, &aObjSize, pRecord->aTextId.nTxBxS, 2910 pRecord->aTextId.nSequence, nGrafAnchorCp, pRetFrmFmt, 2911 (pSdrTextObj != pTrueObject) || (0 != pGroupObject), 2912 bEraseThisObject, 0, 0, 0, 0, pRecord); 2913 2914 // wurde dieses Objekt ersetzt ?? 2915 if (bEraseThisObject) 2916 { 2917 if( pGroupObject || (pSdrTextObj != pTrueObject) ) 2918 { 2919 // Objekt wurde bereits (in der Gruppe und) der Drawing-Page 2920 // durch ein neues SdrGrafObj ersetzt. 2921 2922 SdrObject* pNewObj = pGroupObject ? 2923 pGroupObject->GetSubList()->GetObj(nOrdNum) : pTrueObject; 2924 if (pSdrTextObj != pNewObj) 2925 { 2926 // Objekt in der Z-Order-Liste ersetzen 2927 pMSDffManager->ExchangeInShapeOrder(pSdrTextObj, 0,0, pNewObj); 2928 // Objekt jetzt noch loeschen 2929 SdrObject::Free( pRecord->pObj ); 2930 // und das neue Objekt merken. 2931 pRecord->pObj = pNewObj; 2932 } 2933 } 2934 else 2935 { 2936 // Objekt aus der Z-Order-Liste loeschen 2937 pMSDffManager->RemoveFromShapeOrder( pSdrTextObj ); 2938 // Objekt aus der Drawing-Page rausnehmen 2939 if( pSdrTextObj->GetPage() ) 2940 pDrawPg->RemoveObject( pSdrTextObj->GetOrdNum() ); 2941 // und FrameFormat entfernen, da durch Grafik ersetzt (dies 2942 // loescht auch das Objekt) 2943 rDoc.DelFrmFmt( pRetFrmFmt ); 2944 pRetFrmFmt = 0; 2945 // auch den Objektmerker loeschen 2946 pRecord->pObj = 0; 2947 } 2948 } 2949 else 2950 { 2951 // ww8-default Randabstand einsetzen 2952 SfxItemSet aItemSet(pDrawModel->GetItemPool(), 2953 SDRATTR_TEXT_LEFTDIST, SDRATTR_TEXT_LOWERDIST); 2954 aItemSet.Put( SdrTextLeftDistItem( pRecord->nDxTextLeft ) ); 2955 aItemSet.Put( SdrTextRightDistItem( pRecord->nDxTextRight ) ); 2956 aItemSet.Put( SdrTextUpperDistItem( pRecord->nDyTextTop ) ); 2957 aItemSet.Put( SdrTextLowerDistItem( pRecord->nDyTextBottom ) ); 2958 pSdrTextObj->SetMergedItemSetAndBroadcast(aItemSet); 2959 } 2960 } 2961 return pRetFrmFmt; 2962 } 2963 2964 SwFlyFrmFmt* SwWW8ImplReader::ConvertDrawTextToFly(SdrObject* &rpObject, 2965 SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, RndStdIds eAnchor, 2966 WW8_FSPA *pF, SfxItemSet &rFlySet) 2967 { 2968 SwFlyFrmFmt* pRetFrmFmt = 0; 2969 long nStartCp; 2970 long nEndCp; 2971 2972 // Pruefen, ob in dieser Textbox-Kette denn Text enthalten ist. ( 2973 // Umwandeln einer leeren Kette in Rahmen waere Unsinn. ) 2974 if ( TxbxChainContainsRealText(pRecord->aTextId.nTxBxS,nStartCp,nEndCp) ) 2975 { 2976 // Der Text wird nicht in das SdrTextObj eingelesen! Stattdessen wird 2977 // ein Rahmen eingefuegt und der Text von nStartCp bis nEndCp dort 2978 // hinein gelesen. 2979 // 2980 // Vorteil: im Rahmen sind viel mehr Attribute moeglich als in der 2981 // Edit-Enging, und es koennen auch Felder, OLEs oder Grafiken darin 2982 // sein... 2983 2984 Rectangle aInnerDist(pRecord->nDxTextLeft, pRecord->nDyTextTop, 2985 pRecord->nDxTextRight, pRecord->nDyTextBottom); 2986 2987 SwFmtFrmSize aFrmSize(ATT_FIX_SIZE, pF->nXaRight - pF->nXaLeft, pF->nYaBottom - pF->nYaTop); 2988 aFrmSize.SetWidthSizeType(pRecord->bAutoWidth ? ATT_VAR_SIZE : ATT_FIX_SIZE); 2989 rFlySet.Put(aFrmSize); 2990 2991 MatchSdrItemsIntoFlySet( rpObject, rFlySet, pRecord->eLineStyle, 2992 pRecord->eShapeType, aInnerDist ); 2993 2994 2995 SdrTextObj *pSdrTextObj = PTR_CAST(SdrTextObj, rpObject); 2996 if (pSdrTextObj && pSdrTextObj->IsVerticalWriting()) 2997 rFlySet.Put(SvxFrameDirectionItem(FRMDIR_VERT_TOP_RIGHT, RES_FRAMEDIR)); 2998 2999 pRetFrmFmt = rDoc.MakeFlySection(eAnchor, pPaM->GetPoint(), &rFlySet); 3000 ASSERT(pRetFrmFmt->GetAnchor().GetAnchorId() == eAnchor, 3001 "Not the anchor type requested!"); 3002 3003 // falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste 3004 // entsprechend korrigieren (oder Eintrag loeschen) 3005 rpOurNewObject = CreateContactObject(pRetFrmFmt); 3006 3007 // altes Objekt aus der Z-Order-Liste entfernen 3008 pMSDffManager->RemoveFromShapeOrder( rpObject ); 3009 3010 // und das Objekt loeschen 3011 SdrObject::Free( rpObject ); 3012 /* 3013 Achtung: ab jetzt nur noch pOrgShapeObject 3014 abfragen! 3015 */ 3016 3017 if (rpOurNewObject) 3018 { 3019 /* 3020 #96375# 3021 We do not store our rpOutNewObject in the ShapeOrder because we 3022 have a FrmFmt from which we can regenerate the contact object when 3023 we need it. Because, we can have frames anchored to paragraphs in 3024 header/footers and we can copy header/footers, if we do copy a 3025 header/footer with a nonpage anchored frame in it then the contact 3026 objects are invalidated. Under this condition the FrmFmt will be 3027 updated to reflect this change and can be used to get a new 3028 contact object, while a raw rpOutNewObject stored here becomes 3029 deleted and useless. 3030 */ 3031 pMSDffManager->StoreShapeOrder(pF->nSpId, 3032 (((sal_uLong)pRecord->aTextId.nTxBxS) << 16) + 3033 pRecord->aTextId.nSequence, 0, pRetFrmFmt); 3034 3035 // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit 3036 // in SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden 3037 // kann !!! 3038 if (!rpOurNewObject->IsInserted()) 3039 { 3040 // --> OD 2004-12-13 #117915# - pass information, if object 3041 // is in page header|footer to method. 3042 pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId, 3043 bIsHeader || bIsFooter ); 3044 // <-- 3045 } 3046 } 3047 3048 // Box-0 erhaelt den Text fuer die ganze Kette! 3049 if( !pRecord->aTextId.nSequence ) 3050 { 3051 // rette Flags u.ae. und setze sie zurueck 3052 WW8ReaderSave aSave( this ); 3053 3054 MoveInsideFly(pRetFrmFmt); 3055 3056 SwNodeIndex aStart(pPaM->GetPoint()->nNode); 3057 3058 pWWZOrder->InsideEscher(pF->nSpId); 3059 3060 // lies den Text ein 3061 bTxbxFlySection = true; 3062 bool bJoined = ReadText(nStartCp, (nEndCp-nStartCp), 3063 MAN_MAINTEXT == pPlcxMan->GetManType() ? 3064 MAN_TXBX : MAN_TXBX_HDFT); 3065 3066 pWWZOrder->OutsideEscher(); 3067 3068 MoveOutsideFly(pRetFrmFmt, aSave.GetStartPos(),!bJoined); 3069 3070 aSave.Restore( this ); 3071 } 3072 } 3073 return pRetFrmFmt; 3074 } 3075 3076 void MatchEscherMirrorIntoFlySet(const SvxMSDffImportRec &rRecord, 3077 SfxItemSet &rFlySet) 3078 { 3079 if (rRecord.bVFlip || rRecord.bHFlip) 3080 { 3081 MirrorGraph eType(RES_MIRROR_GRAPH_DONT); 3082 if (rRecord.bVFlip && rRecord.bHFlip) 3083 eType = RES_MIRROR_GRAPH_BOTH; 3084 else if (rRecord.bVFlip) 3085 eType = RES_MIRROR_GRAPH_HOR; 3086 else 3087 eType = RES_MIRROR_GRAPH_VERT; 3088 rFlySet.Put( SwMirrorGrf(eType) ); 3089 } 3090 } 3091 3092 SwFlyFrmFmt* SwWW8ImplReader::ImportReplaceableDrawables( SdrObject* &rpObject, 3093 SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, WW8_FSPA *pF, 3094 SfxItemSet &rFlySet ) 3095 { 3096 SwFlyFrmFmt* pRetFrmFmt = 0; 3097 long nWidthTw = pF->nXaRight - pF->nXaLeft; 3098 if (0 > nWidthTw) 3099 nWidthTw = 0; 3100 long nHeightTw = pF->nYaBottom - pF->nYaTop; 3101 if (0 > nHeightTw) 3102 nHeightTw = 0; 3103 3104 ProcessEscherAlign(pRecord, pF, rFlySet, true); 3105 3106 rFlySet.Put(SwFmtFrmSize(ATT_FIX_SIZE, nWidthTw, nHeightTw)); 3107 3108 SfxItemSet aGrSet(rDoc.GetAttrPool(), RES_GRFATR_BEGIN, RES_GRFATR_END-1); 3109 3110 if (pRecord) 3111 { 3112 //Note that the escher inner distance only seems to be honoured in 3113 //word for textboxes, not for graphics and ole objects. 3114 Rectangle aInnerDist(0, 0, 0, 0); 3115 3116 MatchSdrItemsIntoFlySet(rpObject, rFlySet, pRecord->eLineStyle, 3117 pRecord->eShapeType, aInnerDist); 3118 3119 MatchEscherMirrorIntoFlySet(*pRecord, aGrSet); 3120 } 3121 3122 String aObjectName(rpObject->GetName()); 3123 if (OBJ_OLE2 == SdrObjKind(rpObject->GetObjIdentifier())) 3124 pRetFrmFmt = InsertOle(*((SdrOle2Obj*)rpObject), rFlySet, aGrSet); 3125 else 3126 { 3127 const SdrGrafObj *pGrf= (const SdrGrafObj*)rpObject; 3128 bool bDone = false; 3129 if (pGrf->IsLinkedGraphic() && pGrf->GetFileName().Len()) 3130 { 3131 GraphicType eType = pGrf->GetGraphicType(); 3132 String aGrfName( 3133 URIHelper::SmartRel2Abs( 3134 INetURLObject(sBaseURL), pGrf->GetFileName(), 3135 URIHelper::GetMaybeFileHdl())); 3136 // --> OD 2005-07-04 #124117# - correction of fix for issue #i10939#: 3137 // One of the two conditions have to be true to insert the graphic 3138 // as a linked graphic - 3139 if (GRAPHIC_NONE == eType || CanUseRemoteLink(aGrfName)) 3140 // <-- 3141 { 3142 pRetFrmFmt = rDoc.Insert(*pPaM, aGrfName, aEmptyStr, 0, 3143 &rFlySet, &aGrSet, NULL); 3144 bDone = true; 3145 } 3146 } 3147 if (!bDone) 3148 { 3149 const Graphic& rGraph = pGrf->GetGraphic(); 3150 pRetFrmFmt = rDoc.Insert(*pPaM, aEmptyStr, aEmptyStr, &rGraph, 3151 &rFlySet, &aGrSet, NULL); 3152 } 3153 } 3154 3155 if (pRetFrmFmt) 3156 { 3157 if( pRecord ) 3158 { 3159 if( OBJ_OLE2 != SdrObjKind(rpObject->GetObjIdentifier()) ) 3160 SetAttributesAtGrfNode( pRecord, pRetFrmFmt, pF ); 3161 } 3162 // mehrfaches Auftreten gleicher Grafik-Namen vermeiden 3163 maGrfNameGenerator.SetUniqueGraphName(pRetFrmFmt, aObjectName); 3164 } 3165 //falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste 3166 //entsprechend korrigieren (oder Eintrag loeschen) 3167 rpOurNewObject = CreateContactObject(pRetFrmFmt); 3168 3169 // altes Objekt aus der Z-Order-Liste entfernen 3170 pMSDffManager->RemoveFromShapeOrder( rpObject ); 3171 // aus der Drawing-Page rausnehmen 3172 if( rpObject->GetPage() ) 3173 pDrawPg->RemoveObject( rpObject->GetOrdNum() ); 3174 3175 // und das Objekt loeschen 3176 SdrObject::Free( rpObject ); 3177 /* 3178 Achtung: ab jetzt nur noch pOrgShapeObject abfragen! 3179 */ 3180 3181 // Kontakt-Objekt in die Z-Order-Liste und die Page aufnehmen 3182 if (rpOurNewObject) 3183 { 3184 if (!bHdFtFtnEdn) 3185 pMSDffManager->StoreShapeOrder(pF->nSpId, 0, rpOurNewObject, 0 ); 3186 3187 // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit in 3188 // SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden kann !!! 3189 if (!rpOurNewObject->IsInserted()) 3190 { 3191 // --> OD 2004-12-13 #117915# - pass information, if object 3192 // is in page header|footer to method. 3193 pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId, 3194 bIsHeader || bIsFooter ); 3195 // <-- 3196 } 3197 } 3198 return pRetFrmFmt; 3199 } 3200 3201 void SwWW8ImplReader::GrafikCtor() // Fuer SVDraw und VCControls und Escher 3202 { 3203 if (!pDrawModel) 3204 { 3205 // --> OD 2005-08-08 #i52858# - method name changed 3206 rDoc.GetOrCreateDrawModel(); 3207 // <-- 3208 pDrawModel = rDoc.GetDrawModel(); 3209 ASSERT(pDrawModel, "Kann DrawModel nicht anlegen"); 3210 pDrawPg = pDrawModel->GetPage(0); 3211 3212 pMSDffManager = new SwMSDffManager(*this); 3213 pMSDffManager->SetModel(pDrawModel, 1440); 3214 /* 3215 #79055# 3216 Now the dff manager always needs a controls //converter as well, but a 3217 control converter may still exist //without a dffmanager. cmc 3218 */ 3219 pFormImpl = new SwMSConvertControls(mpDocShell, pPaM); 3220 3221 pWWZOrder = new wwZOrderer(sw::util::SetLayer(rDoc), pDrawPg, 3222 pMSDffManager ? pMSDffManager->GetShapeOrders() : 0); 3223 } 3224 } 3225 3226 void SwWW8ImplReader::GrafikDtor() 3227 { 3228 DELETEZ(mpDrawEditEngine); // evtl. von Grafik angelegt 3229 DELETEZ(pWWZOrder); // dito 3230 } 3231 3232 void SwWW8FltAnchorStack::AddAnchor(const SwPosition& rPos, SwFrmFmt *pFmt) 3233 { 3234 ASSERT(pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR, 3235 "Don't use fltanchors with inline frames, slap!"); 3236 NewAttr(rPos, SwFltAnchor(pFmt)); 3237 } 3238 3239 void SwWW8FltAnchorStack::Flush() 3240 { 3241 sal_uInt16 nCnt = static_cast< sal_uInt16 >(Count()); 3242 for (sal_uInt16 i=0; i < nCnt; ++i) 3243 { 3244 SwFltStackEntry *pEntry = (*this)[i]; 3245 SwPosition aDummy(pEntry->nMkNode); 3246 SetAttrInDoc(aDummy,pEntry); 3247 DeleteAndDestroy(i--); 3248 --nCnt; 3249 } 3250 } 3251 3252 /* vi:set tabstop=4 shiftwidth=4 expandtab: */ 3253