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