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 2238 SvxMSDffImportRec aRecordFromFSPA; 2239 if (!pRecord) 2240 { 2241 pRecord = &aRecordFromFSPA; 2242 pRecord->nXRelTo = pFSPA->nbx; 2243 pRecord->nYRelTo = pFSPA->nby; 2244 } 2245 2246 // nXAlign - abs. Position, Left, Centered, Right, Inside, Outside 2247 // nYAlign - abs. Position, Top, Centered, Bottom, Inside, Outside 2248 2249 // nXRelTo - Page printable area, Page, Column, Character 2250 // nYRelTo - Page printable area, Page, Paragraph, Line 2251 2252 const sal_uInt32 nCntXAlign = 6; 2253 const sal_uInt32 nCntYAlign = 6; 2254 2255 const sal_uInt32 nCntRelTo = 4; 2256 2257 sal_uInt32 nXAlign = nCntXAlign > pRecord->nXAlign ? pRecord->nXAlign : 1; 2258 sal_uInt32 nYAlign = nCntYAlign > pRecord->nYAlign ? pRecord->nYAlign : 1; 2259 2260 if (pFSPA) 2261 { 2262 /* 2263 #74188# #i15718# #i19008# 2264 Strangely in this case the FSPA value seems to be considered before 2265 the newer escher nXRelTo record. 2266 */ 2267 // --> OD 2005-08-04 #i52565# - correct condition checking: 2268 // first check, if <nXRelTo> and <nYRelTo> have default values. This 2269 // is a hint that these values aren't set by the escher import - see 2270 // method <SwMSDffManager::ProcessObj(..)>. Then, check if for each 2271 // values, if it differs from the one in the FSPA. 2272 if ( pRecord->nXRelTo == 2 && pRecord->nYRelTo == 2 ) 2273 { 2274 // if <nYRelTo> differs from <FSPA.nby> overwrite <nYRelTo> 2275 if ( pFSPA->nby != pRecord->nYRelTo ) 2276 { 2277 pRecord->nYRelTo = pFSPA->nby; 2278 } 2279 } 2280 // <-- 2281 } 2282 2283 sal_uInt32 nXRelTo = nCntRelTo > pRecord->nXRelTo ? pRecord->nXRelTo : 1; 2284 sal_uInt32 nYRelTo = nCntRelTo > pRecord->nYRelTo ? pRecord->nYRelTo : 1; 2285 2286 // --> OD 2005-03-03 #i43718# 2287 RndStdIds eAnchor = IsInlineEscherHack() ? FLY_AS_CHAR : FLY_AT_CHAR; 2288 // <-- 2289 2290 SwFmtAnchor aAnchor( eAnchor ); 2291 aAnchor.SetAnchor( pPaM->GetPoint() ); 2292 rFlySet.Put( aAnchor ); 2293 2294 if (pFSPA) 2295 { 2296 // OD 14.10.2003 #i18732# 2297 //Given new layout where everything is changed to be anchored to 2298 //character the following 4 tables may need to be changed. 2299 2300 // horizontal Adjustment 2301 static const sal_Int16 aHoriOriTab[ nCntXAlign ] = 2302 { 2303 text::HoriOrientation::NONE, // From left position 2304 text::HoriOrientation::LEFT, // left 2305 text::HoriOrientation::CENTER, // centered 2306 text::HoriOrientation::RIGHT, // right 2307 // --> OD 2004-12-06 #i36649# 2308 // - inside -> text::HoriOrientation::LEFT and outside -> text::HoriOrientation::RIGHT 2309 text::HoriOrientation::LEFT, // inside 2310 text::HoriOrientation::RIGHT // outside 2311 // <-- 2312 }; 2313 2314 2315 // generic vertical Adjustment 2316 static const sal_Int16 aVertOriTab[ nCntYAlign ] = 2317 { 2318 text::VertOrientation::NONE, // From Top position 2319 text::VertOrientation::TOP, // top 2320 text::VertOrientation::CENTER, // centered 2321 text::VertOrientation::BOTTOM, // bottom 2322 text::VertOrientation::LINE_TOP, // inside (obscure) 2323 text::VertOrientation::LINE_BOTTOM // outside (obscure) 2324 }; 2325 2326 // CMC,OD 24.11.2003 #i22673# - to-line vertical alignment 2327 static const sal_Int16 aToLineVertOriTab[ nCntYAlign ] = 2328 { 2329 text::VertOrientation::NONE, // below 2330 text::VertOrientation::LINE_BOTTOM, // top 2331 text::VertOrientation::LINE_CENTER, // centered 2332 text::VertOrientation::LINE_TOP, // bottom 2333 text::VertOrientation::LINE_BOTTOM, // inside (obscure) 2334 text::VertOrientation::LINE_TOP // outside (obscure) 2335 }; 2336 2337 // Adjustment is horizontally relative to... 2338 static const sal_Int16 aHoriRelOriTab[nCntRelTo] = 2339 { 2340 text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin 2341 text::RelOrientation::PAGE_FRAME, // 1 is page margin 2342 text::RelOrientation::FRAME, // 2 is relative to column 2343 text::RelOrientation::CHAR // 3 is relative to character 2344 }; 2345 2346 // Adjustment is vertically relative to... 2347 // CMC, OD 24.11.2003 #i22673# - adjustment for new vertical alignment 2348 // at top of line. 2349 static const sal_Int16 aVertRelOriTab[nCntRelTo] = 2350 { 2351 text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin 2352 text::RelOrientation::PAGE_FRAME, // 1 is page margin 2353 text::RelOrientation::FRAME, // 2 is relative to paragraph 2354 text::RelOrientation::TEXT_LINE // 3 is relative to line 2355 }; 2356 2357 sal_Int16 eHoriOri = aHoriOriTab[ nXAlign ]; 2358 sal_Int16 eHoriRel = aHoriRelOriTab[ nXRelTo ]; 2359 2360 // --> OD 2004-12-06 #i36649# - adjustments for certain alignments 2361 if ( eHoriOri == text::HoriOrientation::LEFT && eHoriRel == text::RelOrientation::PAGE_FRAME ) 2362 { 2363 // convert 'left to page' to 'from left -<width> to page text area' 2364 eHoriOri = text::HoriOrientation::NONE; 2365 eHoriRel = text::RelOrientation::PAGE_PRINT_AREA; 2366 const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft; 2367 pFSPA->nXaLeft = -nWidth; 2368 pFSPA->nXaRight = 0; 2369 } 2370 else if ( eHoriOri == text::HoriOrientation::RIGHT && eHoriRel == text::RelOrientation::PAGE_FRAME ) 2371 { 2372 // convert 'right to page' to 'from left 0 to right page border' 2373 eHoriOri = text::HoriOrientation::NONE; 2374 eHoriRel = text::RelOrientation::PAGE_RIGHT; 2375 const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft; 2376 pFSPA->nXaLeft = 0; 2377 pFSPA->nXaRight = nWidth; 2378 } 2379 // <-- 2380 2381 // --> OD 2005-02-07 #i24255# - position of floating screen objects in 2382 // R2L layout are given in L2R layout, thus convert them of all 2383 // floating screen objects, which are imported. 2384 { 2385 //#109311# Miserable miserable hack. 2386 SwTwips nWidth = (pFSPA->nXaRight - pFSPA->nXaLeft); 2387 SwTwips nLeft = pFSPA->nXaLeft; 2388 if (MiserableRTLGraphicsHack(nLeft, nWidth, eHoriOri, 2389 eHoriRel)) 2390 { 2391 pFSPA->nXaLeft = nLeft; 2392 pFSPA->nXaRight = pFSPA->nXaLeft + nWidth; 2393 } 2394 } 2395 // <-- 2396 2397 // --> OD 2005-01-20 #118546# - if the object is anchored inside 2398 // a table cell, is horizontal aligned at frame|character and 2399 // has wrap through, but its attribute 'layout in table cell' isn't set, 2400 // convert its horizontal alignment to page text area. 2401 // --> OD 2008-04-10 #i84783# - use new method <IsObjectLayoutInTableCell()> 2402 if ( nInTable && 2403 ( eHoriRel == text::RelOrientation::FRAME || eHoriRel == text::RelOrientation::CHAR ) && 2404 pFSPA->nwr == 3 && 2405 !IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell ) ) 2406 { 2407 eHoriRel = text::RelOrientation::PAGE_PRINT_AREA; 2408 } 2409 // <-- 2410 2411 SwFmtHoriOrient aHoriOri(MakeSafePositioningValue(pFSPA->nXaLeft), 2412 eHoriOri, eHoriRel); 2413 if( 4 <= nXAlign ) 2414 aHoriOri.SetPosToggle(true); 2415 rFlySet.Put( aHoriOri ); 2416 2417 //Writer honours this wrap distance when aligned as "left" or "right", 2418 //Word doesn't. Writer doesn't honour it when its "from left". 2419 if (eHoriOri == text::HoriOrientation::LEFT) 2420 pRecord->nDxWrapDistLeft=0; 2421 else if (eHoriOri == text::HoriOrientation::RIGHT) 2422 pRecord->nDxWrapDistRight=0; 2423 2424 sal_Int16 eVertRel; 2425 // OD 14.10.2003 #i18732# 2426 eVertRel = aVertRelOriTab[ nYRelTo ]; 2427 // CMC, OD 24.11.2003 #i22673# - fill <eVertOri> in dependence of <eVertRel> 2428 sal_Int16 eVertOri; 2429 if ( eVertRel == text::RelOrientation::TEXT_LINE ) 2430 { 2431 eVertOri = aToLineVertOriTab[ nYAlign ]; 2432 } 2433 else 2434 { 2435 eVertOri = aVertOriTab[ nYAlign ]; 2436 } 2437 2438 //Below line in word is a positive value, while in writer its 2439 //negative 2440 long nYPos = pFSPA->nYaTop; 2441 // CMC, OD 24.11.2003 #i22673# 2442 if ((eVertRel == text::RelOrientation::TEXT_LINE) && (eVertOri == text::VertOrientation::NONE)) 2443 nYPos = -nYPos; 2444 2445 rFlySet.Put(SwFmtVertOrient(MakeSafePositioningValue(nYPos), 2446 eVertOri, eVertRel)); 2447 2448 if ( 2449 (pFSPA->nYaTop < 0) && (eVertOri == text::VertOrientation::NONE) && 2450 ((eAnchor == FLY_AT_PARA) || (eAnchor == FLY_AT_CHAR)) 2451 ) 2452 { 2453 maTracer.Log(sw::log::eNegativeVertPlacement); 2454 } 2455 } 2456 2457 return eAnchor; 2458 } 2459 2460 // --> OD 2008-04-10 #i84783# 2461 bool SwWW8ImplReader::IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTableCell ) const 2462 { 2463 bool bIsObjectLayoutInTableCell = false; 2464 2465 if ( bVer8 ) 2466 { 2467 const sal_uInt16 nWWVersion = pWwFib->nProduct & 0xE000; 2468 switch ( nWWVersion ) 2469 { 2470 case 0x0000: // version 8 aka Microsoft Word 97 2471 { 2472 bIsObjectLayoutInTableCell = false; 2473 ASSERT( nLayoutInTableCell == 0xFFFFFFFF, 2474 "no explicit object attribute layout in table cell expected." ); 2475 } 2476 break; 2477 case 0x2000: // version 9 aka Microsoft Word 2000 2478 case 0x4000: // version 10 aka Microsoft Word 2002 2479 case 0x6000: // version 11 aka Microsoft Word 2003 2480 case 0x8000: // version 12 aka Microsoft Word 2007 2481 case 0xC000: // version 14 aka Microsoft Word 2010 2482 { 2483 // --> OD 2009-01-13 #i98037# 2484 // adjustment of conditions needed after deeper analysis of 2485 // certain test cases. 2486 if ( nLayoutInTableCell == 0xFFFFFFFF || // no explicit attribute value given 2487 nLayoutInTableCell == 0x80008000 || 2488 ( nLayoutInTableCell & 0x02000000 && 2489 !(nLayoutInTableCell & 0x80000000 ) ) ) 2490 // <-- 2491 { 2492 bIsObjectLayoutInTableCell = true; 2493 } 2494 else 2495 { 2496 bIsObjectLayoutInTableCell = false; 2497 } 2498 } 2499 break; 2500 default: 2501 { 2502 ASSERT( false, 2503 "unknown version." ); 2504 } 2505 } 2506 } 2507 2508 return bIsObjectLayoutInTableCell; 2509 } 2510 // <-- 2511 2512 SwFrmFmt* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp ) 2513 { 2514 if( nIniFlags & WW8FL_NO_GRAFLAYER ) 2515 return 0; 2516 2517 ::SetProgressState(nProgress, mpDocShell); // Update 2518 2519 nDrawCpO = pWwFib->GetBaseCp(pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX); 2520 2521 GrafikCtor(); 2522 2523 WW8PLCFspecial* pPF = pPlcxMan->GetFdoa(); 2524 if( !pPF ) 2525 { 2526 ASSERT( !this, "Where is the grapic (1) ?" ); 2527 return 0; 2528 } 2529 2530 if( bVer67 ) 2531 { 2532 long nOldPos = pStrm->Tell(); 2533 2534 nDrawXOfs = nDrawYOfs = 0; 2535 ReadGrafLayer1( pPF, nGrafAnchorCp ); 2536 2537 pStrm->Seek( nOldPos ); 2538 return 0; 2539 } 2540 2541 //Normal case of Word 8+ version stuff 2542 pPF->SeekPos( nGrafAnchorCp ); 2543 2544 WW8_FC nStartFc; 2545 void* pF0; 2546 if( !pPF->Get( nStartFc, pF0 ) ){ 2547 ASSERT( !this, "+Wo ist die Grafik (2) ?" ); 2548 return 0; 2549 } 2550 2551 WW8_FSPA_SHADOW* pFS = (WW8_FSPA_SHADOW*)pF0; 2552 WW8_FSPA* pF; 2553 #ifdef __WW8_NEEDS_COPY 2554 WW8_FSPA aFSFA; 2555 pF = &aFSFA; 2556 WW8FSPAShadowToReal( pFS, pF ); 2557 #else 2558 pF = (WW8_FSPA*)pFS; 2559 #endif // defined __WW8_NEEDS_COPY 2560 if( !pF->nSpId ) 2561 { 2562 ASSERT( !this, "+Wo ist die Grafik (3) ?" ); 2563 return 0; 2564 } 2565 2566 if (!pMSDffManager->GetModel()) 2567 pMSDffManager->SetModel(pDrawModel, 1440); 2568 2569 2570 Rectangle aRect(pF->nXaLeft, pF->nYaTop, pF->nXaRight, pF->nYaBottom); 2571 SvxMSDffImportData aData( aRect ); 2572 2573 /* 2574 #i20540# 2575 The SdrOle2Obj will try and manage any ole objects it finds, causing all 2576 sorts of trouble later on 2577 */ 2578 SwDocShell* pPersist = rDoc.GetDocShell(); 2579 rDoc.SetDocShell(0); //#i20540# Persist guard 2580 2581 SdrObject* pObject = 0; 2582 bool bOk = (pMSDffManager->GetShape(pF->nSpId, pObject, aData) && pObject); 2583 2584 rDoc.SetDocShell(pPersist); //#i20540# Persist guard 2585 2586 if (!bOk) 2587 { 2588 ASSERT( !this, "Where is the Shape ?" ); 2589 return 0; 2590 } 2591 2592 bool bDone = false; 2593 SdrObject* pOurNewObject = 0; 2594 bool bReplaceable = false; 2595 2596 switch (SdrObjKind(pObject->GetObjIdentifier())) 2597 { 2598 case OBJ_GRAF: 2599 bReplaceable = true; 2600 bDone = true; 2601 break; 2602 case OBJ_OLE2: 2603 bReplaceable = true; 2604 break; 2605 default: 2606 break; 2607 2608 } 2609 2610 // OD 14.10.2003 - keep wrapping of objects in page header/footer. 2611 /* 2612 //#108778# when in a header or footer word appears to treat all elements 2613 //are wrap through 2614 if (bIsHeader || bIsFooter) 2615 pF->nwr = 3; 2616 */ 2617 2618 // Umfluss-Modus ermitteln 2619 SfxItemSet aFlySet(rDoc.GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1); 2620 SwSurround eSurround = SURROUND_PARALLEL; 2621 bool bContour = false; 2622 switch (pF->nwr) 2623 { 2624 case 0: //0 like 2, but doesn't require absolute object 2625 case 2: //2 wrap around absolute object 2626 eSurround = SURROUND_PARALLEL; 2627 break; 2628 case 1: //1 no text next to shape 2629 eSurround = SURROUND_NONE; 2630 break; 2631 case 3: //3 wrap as if no object present 2632 eSurround = SURROUND_THROUGHT; 2633 break; 2634 case 4: //4 wrap tightly around object 2635 case 5: //5 wrap tightly, but allow holes 2636 eSurround = SURROUND_PARALLEL; 2637 bContour = true; 2638 break; 2639 } 2640 2641 // bei Modus 2 oder 4 auch den Zusatzparameter beruecksichtigen 2642 if ( (2 == pF->nwr) || (4 == pF->nwr) ) 2643 { 2644 switch( pF->nwrk ) 2645 { 2646 //0 wrap both sides 2647 case 0: 2648 eSurround = SURROUND_PARALLEL; 2649 break; 2650 //1 wrap only on left 2651 case 1: 2652 eSurround = SURROUND_LEFT; 2653 break; 2654 //2 wrap only on right 2655 case 2: 2656 eSurround = SURROUND_RIGHT; 2657 break; 2658 //3 wrap only on largest side 2659 case 3: 2660 eSurround = SURROUND_IDEAL; 2661 break; 2662 } 2663 } 2664 2665 SwFmtSurround aSur( eSurround ); 2666 aSur.SetContour( bContour ); 2667 aSur.SetOutside(true); // Winword kann nur Aussen-Konturen 2668 aFlySet.Put( aSur ); 2669 2670 // eingelesenes Objekt (kann eine ganze Gruppe sein) jetzt korrekt 2671 // positionieren usw. 2672 2673 ASSERT(!((aData.GetRecCount() != 1) && bReplaceable), 2674 "Replaceable drawing with > 1 entries ?"); 2675 2676 if (aData.GetRecCount() != 1) 2677 bReplaceable = false; 2678 2679 SvxMSDffImportRec* pRecord = 0; 2680 /* 2681 Get the record for top level object, so we can get the word anchoring 2682 and wrapping information for it. 2683 */ 2684 sal_uInt16 nRecCount = aData.GetRecCount(); 2685 for (sal_uInt16 nTxbx=0; nTxbx < nRecCount; ++nTxbx ) 2686 { 2687 pRecord = aData.GetRecord( nTxbx ); 2688 if (pRecord && pRecord->pObj == pObject) 2689 break; 2690 else 2691 pRecord = 0; 2692 } 2693 2694 ASSERT(pRecord, "how did that happen?"); 2695 if (!pRecord) 2696 return 0; 2697 2698 // --> OD 2008-04-10 #i84783# 2699 // //cmc: We're in a table, and the element has the magic Word XP bit set 2700 // //to enable layout inside a cell 2701 // // --> OD 2005-08-10 #124714# - undo change made for issue #i33442# 2702 // bool bLayoutInTableCell = ( nInTable && 2703 // pRecord->nLayoutInTableCell & 0x00008000 ); 2704 // // <-- 2705 const bool bLayoutInTableCell = 2706 nInTable && IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell ); 2707 // <-- 2708 2709 // OD 14.10.2003 #i18732# 2710 // Switch on 'follow text flow', 2711 // if object is laid out inside table cell and 2712 // its wrapping isn't 'SURROUND_THROUGH' 2713 if (bLayoutInTableCell && eSurround != SURROUND_THROUGHT) 2714 { 2715 SwFmtFollowTextFlow aFollowTextFlow( sal_True ); 2716 aFlySet.Put( aFollowTextFlow ); 2717 } 2718 2719 2720 //#i21847# 2721 //Some shapes are set to *hidden*, don't import those ones. 2722 if (pRecord->bHidden) 2723 return 0; 2724 2725 // If we are to be "below text" then we are not to be opaque 2726 // #i14045# MM If we are in a header or footer then make the object transparent 2727 // Not exactly like word but close enough for now 2728 2729 // --> OD 2005-03-07 #b6234902# - both flags <bBelowText> and <bDrawHell> 2730 // have to be set to move object into the background. 2731 // --> OD 2005-04-11 #i46794# - it reveals that value of flag <bBelowText> 2732 // can be neglected. 2733 const bool bMoveToBackgrd = pRecord->bDrawHell || 2734 ( ( bIsHeader || bIsFooter ) && pF->nwr == 3 ); 2735 if ( bMoveToBackgrd ) 2736 aFlySet.Put(SvxOpaqueItem(RES_OPAQUE,false)); 2737 2738 String aObjName = pObject->GetName(); 2739 2740 SwFrmFmt* pRetFrmFmt = 0; 2741 if (bReplaceable) 2742 { 2743 //Single graphics or ole objects 2744 pRetFrmFmt = ImportReplaceableDrawables(pObject, pOurNewObject, pRecord, 2745 pF, aFlySet); 2746 } 2747 else 2748 { 2749 //Drawing objects, (e.g. ovals or drawing groups) 2750 if (pF->bRcaSimple) 2751 { 2752 pF->nbx = WW8_FSPA::RelPageBorder; 2753 pF->nby = WW8_FSPA::RelPageBorder; 2754 } 2755 2756 RndStdIds eAnchor = ProcessEscherAlign(pRecord, pF, aFlySet, 2757 bReplaceable); 2758 2759 // Should we, and is it possible to make this into a writer textbox 2760 if ((!(nIniFlags1 & WW8FL_NO_FLY_FOR_TXBX)) && pRecord->bReplaceByFly) 2761 { 2762 pRetFrmFmt = ConvertDrawTextToFly(pObject, pOurNewObject, pRecord, 2763 eAnchor, pF, aFlySet); 2764 if (pRetFrmFmt) 2765 bDone = true; 2766 } 2767 2768 if (!bDone) 2769 { 2770 sw::util::SetLayer aSetLayer(rDoc); 2771 if ( bMoveToBackgrd ) 2772 aSetLayer.SendObjectToHell(*pObject); 2773 else 2774 aSetLayer.SendObjectToHeaven(*pObject); 2775 2776 if (!IsInlineEscherHack()) 2777 { 2778 /* 2779 #97824# Need to make sure that the correct layer ordering is 2780 applied. 2781 */ 2782 // --> OD 2004-12-13 #117915# - pass information, if object 2783 // is in page header|footer to method. 2784 pWWZOrder->InsertEscherObject( pObject, pF->nSpId, 2785 bIsHeader || bIsFooter ); 2786 // <-- 2787 } 2788 else 2789 { 2790 pWWZOrder->InsertTextLayerObject(pObject); 2791 } 2792 2793 pRetFrmFmt = rDoc.Insert(*pPaM, *pObject, &aFlySet, NULL); 2794 2795 ASSERT(pRetFrmFmt->GetAnchor().GetAnchorId() == 2796 eAnchor, "Not the anchor type requested!"); 2797 2798 /* 2799 Insert text if necessary into textboxes contained in groups. 2800 */ 2801 if (aData.HasRecords()) 2802 { 2803 sal_uInt16 nCount = aData.GetRecCount(); 2804 for (sal_uInt16 nTxbx=0; nTxbx < nCount; ++nTxbx) 2805 { 2806 pRecord = aData.GetRecord(nTxbx); 2807 if (pRecord && pRecord->pObj && pRecord->aTextId.nTxBxS) 2808 { // #i52825# pRetFrmFmt can be NULL 2809 pRetFrmFmt = MungeTextIntoDrawBox(pRecord->pObj, 2810 pRecord, nGrafAnchorCp, pRetFrmFmt); 2811 } 2812 } 2813 } 2814 } 2815 } 2816 2817 // --> OD 2005-03-11 #i44344#, #i44681# - positioning attributes already set 2818 if ( pRetFrmFmt /*#i52825# */ && pRetFrmFmt->ISA(SwDrawFrmFmt) ) 2819 { 2820 static_cast<SwDrawFrmFmt*>(pRetFrmFmt)->PosAttrSet(); 2821 } 2822 // <-- 2823 if (!IsInlineEscherHack()) 2824 MapWrapIntoFlyFmt(pRecord, pRetFrmFmt); 2825 2826 // Set frame name with object name 2827 if( aObjName.Len() ) 2828 pRetFrmFmt->SetName( aObjName ); 2829 return AddAutoAnchor(pRetFrmFmt); 2830 } 2831 2832 SwFrmFmt *SwWW8ImplReader::AddAutoAnchor(SwFrmFmt *pFmt) 2833 { 2834 if (pFmt && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR)) 2835 { 2836 sal_uInt16 nTextAreaWidth = static_cast< sal_uInt16 >( maSectionManager.GetPageWidth() - 2837 maSectionManager.GetPageRight() - maSectionManager.GetPageLeft()); 2838 2839 if (pFmt->GetFrmSize().GetSize().Width() > nTextAreaWidth) 2840 maTracer.Log(sw::log::eTooWideAsChar); 2841 } 2842 2843 /* 2844 * anchored to character at the current position will move along the 2845 * paragraph as text is added because we are at the insertion point. 2846 * 2847 * Leave to later and set the correct location then. 2848 */ 2849 if ((pFmt) && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR)) 2850 { 2851 pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFmt); 2852 } 2853 return pFmt; 2854 } 2855 2856 SwFrmFmt* SwWW8ImplReader::MungeTextIntoDrawBox(SdrObject* pTrueObject, 2857 SvxMSDffImportRec *pRecord, long nGrafAnchorCp, SwFrmFmt* pRetFrmFmt) 2858 { 2859 SdrTextObj* pSdrTextObj; 2860 2861 // Pruefen, ob Gruppenobjekt (z.B. zwei Klammern) vorliegt 2862 if (SdrObjGroup* pThisGroup = PTR_CAST(SdrObjGroup, pRecord->pObj)) 2863 { 2864 // Gruppenobjekte haben keinen Text. Fuege ein Textobjekt in die 2865 // Gruppe ein, um den Text zu halten. 2866 pSdrTextObj = new SdrRectObj( OBJ_TEXT, pThisGroup->GetCurrentBoundRect()); 2867 2868 SfxItemSet aSet(pDrawModel->GetItemPool()); 2869 aSet.Put(XFillStyleItem(XFILL_NONE)); 2870 aSet.Put(XLineStyleItem(XLINE_NONE)); 2871 aSet.Put(SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE )); 2872 aSet.Put(SdrTextAutoGrowHeightItem(false)); 2873 aSet.Put(SdrTextAutoGrowWidthItem(false)); 2874 pSdrTextObj->SetMergedItemSet(aSet); 2875 2876 long nAngle = pRecord->nTextRotationAngle; 2877 if ( nAngle ) 2878 { 2879 double a = nAngle*nPi180; 2880 pSdrTextObj->NbcRotate(pSdrTextObj->GetCurrentBoundRect().Center(), nAngle, 2881 sin(a), cos(a) ); 2882 } 2883 2884 pSdrTextObj->NbcSetLayer( pThisGroup->GetLayer() ); 2885 pThisGroup->GetSubList()->NbcInsertObject(pSdrTextObj); 2886 } 2887 else 2888 pSdrTextObj = PTR_CAST(SdrTextObj, pRecord->pObj); 2889 2890 if( pSdrTextObj ) 2891 { 2892 Size aObjSize(pSdrTextObj->GetSnapRect().GetWidth(), 2893 pSdrTextObj->GetSnapRect().GetHeight()); 2894 2895 // Objekt ist Bestandteil einer Gruppe? 2896 SdrObject* pGroupObject = pSdrTextObj->GetUpGroup(); 2897 2898 sal_uInt32 nOrdNum = pSdrTextObj->GetOrdNum(); 2899 bool bEraseThisObject; 2900 InsertTxbxText( pSdrTextObj, &aObjSize, pRecord->aTextId.nTxBxS, 2901 pRecord->aTextId.nSequence, nGrafAnchorCp, pRetFrmFmt, 2902 (pSdrTextObj != pTrueObject) || (0 != pGroupObject), 2903 bEraseThisObject, 0, 0, 0, 0, pRecord); 2904 2905 // wurde dieses Objekt ersetzt ?? 2906 if (bEraseThisObject) 2907 { 2908 if( pGroupObject || (pSdrTextObj != pTrueObject) ) 2909 { 2910 // Objekt wurde bereits (in der Gruppe und) der Drawing-Page 2911 // durch ein neues SdrGrafObj ersetzt. 2912 2913 SdrObject* pNewObj = pGroupObject ? 2914 pGroupObject->GetSubList()->GetObj(nOrdNum) : pTrueObject; 2915 if (pSdrTextObj != pNewObj) 2916 { 2917 // Objekt in der Z-Order-Liste ersetzen 2918 pMSDffManager->ExchangeInShapeOrder(pSdrTextObj, 0,0, pNewObj); 2919 // Objekt jetzt noch loeschen 2920 SdrObject::Free( pRecord->pObj ); 2921 // und das neue Objekt merken. 2922 pRecord->pObj = pNewObj; 2923 } 2924 } 2925 else 2926 { 2927 // Objekt aus der Z-Order-Liste loeschen 2928 pMSDffManager->RemoveFromShapeOrder( pSdrTextObj ); 2929 // Objekt aus der Drawing-Page rausnehmen 2930 if( pSdrTextObj->GetPage() ) 2931 pDrawPg->RemoveObject( pSdrTextObj->GetOrdNum() ); 2932 // und FrameFormat entfernen, da durch Grafik ersetzt (dies 2933 // loescht auch das Objekt) 2934 rDoc.DelFrmFmt( pRetFrmFmt ); 2935 pRetFrmFmt = 0; 2936 // auch den Objektmerker loeschen 2937 pRecord->pObj = 0; 2938 } 2939 } 2940 else 2941 { 2942 // ww8-default Randabstand einsetzen 2943 SfxItemSet aItemSet(pDrawModel->GetItemPool(), 2944 SDRATTR_TEXT_LEFTDIST, SDRATTR_TEXT_LOWERDIST); 2945 aItemSet.Put( SdrTextLeftDistItem( pRecord->nDxTextLeft ) ); 2946 aItemSet.Put( SdrTextRightDistItem( pRecord->nDxTextRight ) ); 2947 aItemSet.Put( SdrTextUpperDistItem( pRecord->nDyTextTop ) ); 2948 aItemSet.Put( SdrTextLowerDistItem( pRecord->nDyTextBottom ) ); 2949 pSdrTextObj->SetMergedItemSetAndBroadcast(aItemSet); 2950 } 2951 } 2952 return pRetFrmFmt; 2953 } 2954 2955 SwFlyFrmFmt* SwWW8ImplReader::ConvertDrawTextToFly(SdrObject* &rpObject, 2956 SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, RndStdIds eAnchor, 2957 WW8_FSPA *pF, SfxItemSet &rFlySet) 2958 { 2959 SwFlyFrmFmt* pRetFrmFmt = 0; 2960 long nStartCp; 2961 long nEndCp; 2962 2963 // Pruefen, ob in dieser Textbox-Kette denn Text enthalten ist. ( 2964 // Umwandeln einer leeren Kette in Rahmen waere Unsinn. ) 2965 if ( TxbxChainContainsRealText(pRecord->aTextId.nTxBxS,nStartCp,nEndCp) ) 2966 { 2967 // Der Text wird nicht in das SdrTextObj eingelesen! Stattdessen wird 2968 // ein Rahmen eingefuegt und der Text von nStartCp bis nEndCp dort 2969 // hinein gelesen. 2970 // 2971 // Vorteil: im Rahmen sind viel mehr Attribute moeglich als in der 2972 // Edit-Enging, und es koennen auch Felder, OLEs oder Grafiken darin 2973 // sein... 2974 2975 Rectangle aInnerDist(pRecord->nDxTextLeft, pRecord->nDyTextTop, 2976 pRecord->nDxTextRight, pRecord->nDyTextBottom); 2977 2978 SwFmtFrmSize aFrmSize(ATT_FIX_SIZE, pF->nXaRight - pF->nXaLeft, pF->nYaBottom - pF->nYaTop); 2979 aFrmSize.SetWidthSizeType(pRecord->bAutoWidth ? ATT_VAR_SIZE : ATT_FIX_SIZE); 2980 rFlySet.Put(aFrmSize); 2981 2982 MatchSdrItemsIntoFlySet( rpObject, rFlySet, pRecord->eLineStyle, 2983 pRecord->eShapeType, aInnerDist ); 2984 2985 2986 SdrTextObj *pSdrTextObj = PTR_CAST(SdrTextObj, rpObject); 2987 if (pSdrTextObj && pSdrTextObj->IsVerticalWriting()) 2988 rFlySet.Put(SvxFrameDirectionItem(FRMDIR_VERT_TOP_RIGHT, RES_FRAMEDIR)); 2989 2990 pRetFrmFmt = rDoc.MakeFlySection(eAnchor, pPaM->GetPoint(), &rFlySet); 2991 ASSERT(pRetFrmFmt->GetAnchor().GetAnchorId() == eAnchor, 2992 "Not the anchor type requested!"); 2993 2994 // falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste 2995 // entsprechend korrigieren (oder Eintrag loeschen) 2996 rpOurNewObject = CreateContactObject(pRetFrmFmt); 2997 2998 // altes Objekt aus der Z-Order-Liste entfernen 2999 pMSDffManager->RemoveFromShapeOrder( rpObject ); 3000 3001 // und das Objekt loeschen 3002 SdrObject::Free( rpObject ); 3003 /* 3004 Achtung: ab jetzt nur noch pOrgShapeObject 3005 abfragen! 3006 */ 3007 3008 if (rpOurNewObject) 3009 { 3010 /* 3011 #96375# 3012 We do not store our rpOutNewObject in the ShapeOrder because we 3013 have a FrmFmt from which we can regenerate the contact object when 3014 we need it. Because, we can have frames anchored to paragraphs in 3015 header/footers and we can copy header/footers, if we do copy a 3016 header/footer with a nonpage anchored frame in it then the contact 3017 objects are invalidated. Under this condition the FrmFmt will be 3018 updated to reflect this change and can be used to get a new 3019 contact object, while a raw rpOutNewObject stored here becomes 3020 deleted and useless. 3021 */ 3022 pMSDffManager->StoreShapeOrder(pF->nSpId, 3023 (((sal_uLong)pRecord->aTextId.nTxBxS) << 16) + 3024 pRecord->aTextId.nSequence, 0, pRetFrmFmt); 3025 3026 // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit 3027 // in SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden 3028 // kann !!! 3029 if (!rpOurNewObject->IsInserted()) 3030 { 3031 // --> OD 2004-12-13 #117915# - pass information, if object 3032 // is in page header|footer to method. 3033 pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId, 3034 bIsHeader || bIsFooter ); 3035 // <-- 3036 } 3037 } 3038 3039 // Box-0 erhaelt den Text fuer die ganze Kette! 3040 if( !pRecord->aTextId.nSequence ) 3041 { 3042 // rette Flags u.ae. und setze sie zurueck 3043 WW8ReaderSave aSave( this ); 3044 3045 MoveInsideFly(pRetFrmFmt); 3046 3047 SwNodeIndex aStart(pPaM->GetPoint()->nNode); 3048 3049 pWWZOrder->InsideEscher(pF->nSpId); 3050 3051 // lies den Text ein 3052 bTxbxFlySection = true; 3053 bool bJoined = ReadText(nStartCp, (nEndCp-nStartCp), 3054 MAN_MAINTEXT == pPlcxMan->GetManType() ? 3055 MAN_TXBX : MAN_TXBX_HDFT); 3056 3057 pWWZOrder->OutsideEscher(); 3058 3059 MoveOutsideFly(pRetFrmFmt, aSave.GetStartPos(),!bJoined); 3060 3061 aSave.Restore( this ); 3062 } 3063 } 3064 return pRetFrmFmt; 3065 } 3066 3067 void MatchEscherMirrorIntoFlySet(const SvxMSDffImportRec &rRecord, 3068 SfxItemSet &rFlySet) 3069 { 3070 if (rRecord.bVFlip || rRecord.bHFlip) 3071 { 3072 MirrorGraph eType(RES_MIRROR_GRAPH_DONT); 3073 if (rRecord.bVFlip && rRecord.bHFlip) 3074 eType = RES_MIRROR_GRAPH_BOTH; 3075 else if (rRecord.bVFlip) 3076 eType = RES_MIRROR_GRAPH_HOR; 3077 else 3078 eType = RES_MIRROR_GRAPH_VERT; 3079 rFlySet.Put( SwMirrorGrf(eType) ); 3080 } 3081 } 3082 3083 SwFlyFrmFmt* SwWW8ImplReader::ImportReplaceableDrawables( SdrObject* &rpObject, 3084 SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, WW8_FSPA *pF, 3085 SfxItemSet &rFlySet ) 3086 { 3087 SwFlyFrmFmt* pRetFrmFmt = 0; 3088 long nWidthTw = pF->nXaRight - pF->nXaLeft; 3089 if (0 > nWidthTw) 3090 nWidthTw = 0; 3091 long nHeightTw = pF->nYaBottom - pF->nYaTop; 3092 if (0 > nHeightTw) 3093 nHeightTw = 0; 3094 3095 ProcessEscherAlign(pRecord, pF, rFlySet, true); 3096 3097 rFlySet.Put(SwFmtFrmSize(ATT_FIX_SIZE, nWidthTw, nHeightTw)); 3098 3099 SfxItemSet aGrSet(rDoc.GetAttrPool(), RES_GRFATR_BEGIN, RES_GRFATR_END-1); 3100 3101 if (pRecord) 3102 { 3103 //Note that the escher inner distance only seems to be honoured in 3104 //word for textboxes, not for graphics and ole objects. 3105 Rectangle aInnerDist(0, 0, 0, 0); 3106 3107 MatchSdrItemsIntoFlySet(rpObject, rFlySet, pRecord->eLineStyle, 3108 pRecord->eShapeType, aInnerDist); 3109 3110 MatchEscherMirrorIntoFlySet(*pRecord, aGrSet); 3111 } 3112 3113 String aObjectName(rpObject->GetName()); 3114 if (OBJ_OLE2 == SdrObjKind(rpObject->GetObjIdentifier())) 3115 pRetFrmFmt = InsertOle(*((SdrOle2Obj*)rpObject), rFlySet, aGrSet); 3116 else 3117 { 3118 const SdrGrafObj *pGrf= (const SdrGrafObj*)rpObject; 3119 bool bDone = false; 3120 if (pGrf->IsLinkedGraphic() && pGrf->GetFileName().Len()) 3121 { 3122 GraphicType eType = pGrf->GetGraphicType(); 3123 String aGrfName( 3124 URIHelper::SmartRel2Abs( 3125 INetURLObject(sBaseURL), pGrf->GetFileName(), 3126 URIHelper::GetMaybeFileHdl())); 3127 // --> OD 2005-07-04 #124117# - correction of fix for issue #i10939#: 3128 // One of the two conditions have to be true to insert the graphic 3129 // as a linked graphic - 3130 if (GRAPHIC_NONE == eType || CanUseRemoteLink(aGrfName)) 3131 // <-- 3132 { 3133 pRetFrmFmt = rDoc.Insert(*pPaM, aGrfName, aEmptyStr, 0, 3134 &rFlySet, &aGrSet, NULL); 3135 bDone = true; 3136 } 3137 } 3138 if (!bDone) 3139 { 3140 const Graphic& rGraph = pGrf->GetGraphic(); 3141 pRetFrmFmt = rDoc.Insert(*pPaM, aEmptyStr, aEmptyStr, &rGraph, 3142 &rFlySet, &aGrSet, NULL); 3143 } 3144 } 3145 3146 if (pRetFrmFmt) 3147 { 3148 if( pRecord ) 3149 { 3150 if( OBJ_OLE2 != SdrObjKind(rpObject->GetObjIdentifier()) ) 3151 SetAttributesAtGrfNode( pRecord, pRetFrmFmt, pF ); 3152 } 3153 // mehrfaches Auftreten gleicher Grafik-Namen vermeiden 3154 maGrfNameGenerator.SetUniqueGraphName(pRetFrmFmt, aObjectName); 3155 } 3156 //falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste 3157 //entsprechend korrigieren (oder Eintrag loeschen) 3158 rpOurNewObject = CreateContactObject(pRetFrmFmt); 3159 3160 // altes Objekt aus der Z-Order-Liste entfernen 3161 pMSDffManager->RemoveFromShapeOrder( rpObject ); 3162 // aus der Drawing-Page rausnehmen 3163 if( rpObject->GetPage() ) 3164 pDrawPg->RemoveObject( rpObject->GetOrdNum() ); 3165 3166 // und das Objekt loeschen 3167 SdrObject::Free( rpObject ); 3168 /* 3169 Achtung: ab jetzt nur noch pOrgShapeObject abfragen! 3170 */ 3171 3172 // Kontakt-Objekt in die Z-Order-Liste und die Page aufnehmen 3173 if (rpOurNewObject) 3174 { 3175 if (!bHdFtFtnEdn) 3176 pMSDffManager->StoreShapeOrder(pF->nSpId, 0, rpOurNewObject, 0 ); 3177 3178 // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit in 3179 // SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden kann !!! 3180 if (!rpOurNewObject->IsInserted()) 3181 { 3182 // --> OD 2004-12-13 #117915# - pass information, if object 3183 // is in page header|footer to method. 3184 pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId, 3185 bIsHeader || bIsFooter ); 3186 // <-- 3187 } 3188 } 3189 return pRetFrmFmt; 3190 } 3191 3192 void SwWW8ImplReader::GrafikCtor() // Fuer SVDraw und VCControls und Escher 3193 { 3194 if (!pDrawModel) 3195 { 3196 // --> OD 2005-08-08 #i52858# - method name changed 3197 rDoc.GetOrCreateDrawModel(); 3198 // <-- 3199 pDrawModel = rDoc.GetDrawModel(); 3200 ASSERT(pDrawModel, "Kann DrawModel nicht anlegen"); 3201 pDrawPg = pDrawModel->GetPage(0); 3202 3203 pMSDffManager = new SwMSDffManager(*this); 3204 pMSDffManager->SetModel(pDrawModel, 1440); 3205 /* 3206 #79055# 3207 Now the dff manager always needs a controls //converter as well, but a 3208 control converter may still exist //without a dffmanager. cmc 3209 */ 3210 pFormImpl = new SwMSConvertControls(mpDocShell, pPaM); 3211 3212 pWWZOrder = new wwZOrderer(sw::util::SetLayer(rDoc), pDrawPg, 3213 pMSDffManager ? pMSDffManager->GetShapeOrders() : 0); 3214 } 3215 } 3216 3217 void SwWW8ImplReader::GrafikDtor() 3218 { 3219 DELETEZ(mpDrawEditEngine); // evtl. von Grafik angelegt 3220 DELETEZ(pWWZOrder); // dito 3221 } 3222 3223 void SwWW8FltAnchorStack::AddAnchor(const SwPosition& rPos, SwFrmFmt *pFmt) 3224 { 3225 ASSERT(pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR, 3226 "Don't use fltanchors with inline frames, slap!"); 3227 NewAttr(rPos, SwFltAnchor(pFmt)); 3228 } 3229 3230 void SwWW8FltAnchorStack::Flush() 3231 { 3232 sal_uInt16 nCnt = static_cast< sal_uInt16 >(Count()); 3233 for (sal_uInt16 i=0; i < nCnt; ++i) 3234 { 3235 SwFltStackEntry *pEntry = (*this)[i]; 3236 SwPosition aDummy(pEntry->nMkNode); 3237 SetAttrInDoc(aDummy,pEntry); 3238 DeleteAndDestroy(i--); 3239 --nCnt; 3240 } 3241 } 3242 3243 /* vi:set tabstop=4 shiftwidth=4 expandtab: */ 3244