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