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