bump product version to 4.1.6.2
[LibreOffice.git] / sw / source / filter / ww8 / ww8graf.cxx
blob3004bbb28e97c4a8b19a59d496ed9466cd6430d4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/string.hxx>
21 #include <svl/urihelper.hxx>
22 #include <hintids.hxx>
23 #include <osl/endian.h>
24 #include <svx/fmglob.hxx>
25 #include <svx/sdtaitm.hxx>
26 #include <editeng/lrspitem.hxx>
27 #include <editeng/udlnitem.hxx>
28 #include <svx/xlineit.hxx>
29 #include <svx/xfillit.hxx>
30 #include <svx/svdmodel.hxx>
31 #include <svx/svdocapt.hxx>
32 #include <svx/sxctitm.hxx>
33 #include <editeng/editeng.hxx>
34 #include <svx/svdpage.hxx>
35 #include <svx/svdopath.hxx>
36 #include <svx/svdocirc.hxx>
37 #include <editeng/outlobj.hxx>
38 #include <svx/svdogrp.hxx>
39 #include <svx/svdograf.hxx>
40 #include <svx/svdoole2.hxx>
41 #include <editeng/colritem.hxx>
42 #include <editeng/fhgtitem.hxx>
43 #include <editeng/postitem.hxx>
44 #include <editeng/adjustitem.hxx>
45 #include <editeng/wghtitem.hxx>
46 #include <editeng/crossedoutitem.hxx>
47 #include <editeng/contouritem.hxx>
48 #include <editeng/shdditem.hxx>
49 #include <editeng/fontitem.hxx>
50 #include <editeng/ulspitem.hxx>
51 #include <svx/svdoattr.hxx>
52 #include <editeng/brushitem.hxx>
53 #include <svx/rectenum.hxx>
54 #include <editeng/opaqitem.hxx>
55 #include <editeng/shaditem.hxx>
56 #include <editeng/boxitem.hxx>
57 #include <editeng/outliner.hxx>
58 #include <editeng/frmdiritem.hxx>
59 #include <svx/xfltrit.hxx>
60 #include <filter/msfilter/msdffimp.hxx>
61 #include <grfatr.hxx> // class SwCropGrf
62 #include <fmtornt.hxx>
63 #include <fmtcntnt.hxx>
64 #include <frmfmt.hxx>
65 #include <fmtanchr.hxx>
66 #include <pam.hxx>
67 #include <doc.hxx>
68 #include <docary.hxx>
69 #include <ndgrf.hxx>
70 #include <ndtxt.hxx>
71 #include <dcontact.hxx>
72 #include <docsh.hxx>
73 #include <mdiexp.hxx> // Progress
74 #include <fmtcnct.hxx>
75 #include "ww8struc.hxx"
76 #include "ww8scan.hxx"
77 #include "ww8par.hxx" // class SwWWImplReader
78 #include "ww8par2.hxx" // SwWW8StyInf
79 #include "ww8graf.hxx"
80 #include <fmtinfmt.hxx>
81 #include <editeng/eeitem.hxx>
82 #include <editeng/flditem.hxx>
83 // #i18732#
84 #include <fmtfollowtextflow.hxx>
85 #include "writerhelper.hxx"
86 #include "writerwordglue.hxx"
87 #include <basegfx/point/b2dpoint.hxx>
88 #include <basegfx/polygon/b2dpolygon.hxx>
89 #include <editeng/editobj.hxx>
90 #include <boost/scoped_ptr.hpp>
91 #include <math.h>
93 using ::editeng::SvxBorderLine;
94 using namespace ::com::sun::star;
95 using namespace sw::types;
96 using namespace sw::util;
98 // Hilfsroutinen
100 Color WW8TransCol(SVBT32 nWC)
102 #if 1 // 1 = Vordefinierte Farben benutzen, 0 = ignorieren
104 // Farbtabelle zum Umrechnen RGB-Werte in vordefinierte Farben
105 // ( Damit bei der Writer-UI die Farbnamen stimmen )
106 // Die Tabelle int im *3er-System* aufgeteilt. Die Grauwerte fehlen,
107 // da sie nicht ins 3er-System passen ( 4 Werte: sw, ws, 2 * grau )
108 static ColorData eColA[] = { // B G R B G R B G R
109 COL_BLACK, COL_RED, COL_LIGHTRED, // 0 0 0, 0 0 1, 0 0 2
110 COL_GREEN, COL_BROWN, COL_BLACK, // 0 1 0, 0 1 1, 0 1 2
111 COL_LIGHTGREEN, COL_BLACK, COL_YELLOW, // 0 2 0, 0 2 1, 0 2 2
112 COL_BLUE, COL_MAGENTA, COL_BLACK, // 1 0 0, 1 0 1, 1 0 2
113 COL_CYAN, COL_LIGHTGRAY, COL_BLACK, // 1 1 0, 1 1 1, 1 1 2
114 COL_BLACK, COL_BLACK, COL_BLACK, // 1 2 0, 1 2 1, 1 2 2
115 COL_LIGHTBLUE, COL_BLACK, COL_LIGHTMAGENTA, // 2 0 0, 2 0 1, 2 0 2
116 COL_BLACK, COL_BLACK, COL_BLACK, // 2 1 0, 2 1 1, 2 1 2
117 COL_LIGHTCYAN, COL_BLACK, COL_WHITE }; // 2 2 0, 2 2 1, 2 2 2
119 // In nWC[3] steht ein Byte, dass in der WW-Doku nicht beschrieben ist.
120 // Die Bedeutung ist anscheinend folgende: Bei 0 ist es eine normale
121 // Farbe, dessen RGB-Wert in nWC[0..2] steht. stehen in nWC[3] die
122 // Werte 0x1, 0x7d oder 0x83, dann ist es ein Grauwert, dessen
123 // Schwarzanteil in 1/2 % in nWC[0] steht.
124 // Ich vermute, dass es auf Bit0 in nWV[3] ankommt, ob es RGB oder Grau ist.
126 if( !( nWC[3] & 0x1 ) && // keine Spezial-Farbe (grau)
127 ( ( nWC[0] == 0 || nWC[0]== 0x80 || nWC[0] == 0xff ) // R-Anteil
128 && ( nWC[1] == 0 || nWC[1]== 0x80 || nWC[1] == 0xff ) // G-Anteil
129 && ( nWC[2] == 0 || nWC[2]== 0x80 || nWC[2] == 0xff ) ) ){// B-Anteil
130 int nIdx = 0; // und nun: Idx-Berechnung im 3er-System
131 for (int i = 2; i >= 0; i--)
133 nIdx *= 3;
134 if (nWC[i])
135 nIdx += ((nWC[i] == 0xff) ? 2 : 1);
137 if (eColA[nIdx] != COL_BLACK)
138 return Color(eColA[nIdx]); // Standard-Color
140 #endif
142 if (nWC[3] & 0x1)
144 //Special colour gray
145 sal_uInt8 u = (sal_uInt8)( (sal_uLong)( 200 - nWC[0] ) * 256 / 200 );
146 return Color(u, u, u);
149 // User-Color
150 return Color(nWC[0], nWC[1], nWC[2]);
153 void wwFrameNamer::SetUniqueGraphName(SwFrmFmt *pFrmFmt, const OUString &rFixed)
155 if (mbIsDisabled || rFixed.isEmpty())
156 return;
158 pFrmFmt->SetName(msSeed+OUString::valueOf(++mnImportedGraphicsCount) + ": " + rFixed);
161 // ReadGrafStart liest die ObjektDaten ein und erzeugt falls noetig einen Anker
162 bool SwWW8ImplReader::ReadGrafStart(void* pData, short nDataSiz,
163 WW8_DPHEAD* pHd, const WW8_DO* pDo, SfxAllItemSet &rSet)
165 if (SVBT16ToShort(pHd->cb) < sizeof(WW8_DPHEAD) + nDataSiz)
167 OSL_ENSURE( !this, "+Grafik-Element: Size ?" );
168 pStrm->SeekRel(SVBT16ToShort(pHd->cb) - sizeof(WW8_DPHEAD));
169 return false;
172 bool bCouldRead = checkRead(*pStrm, pData, nDataSiz);
173 OSL_ENSURE(bCouldRead, "Short Graphic header");
174 if (!bCouldRead)
175 return false;
177 RndStdIds eAnchor = (SVBT8ToByte(pDo->by) < 2) ? FLY_AT_PAGE : FLY_AT_PARA;
178 rSet.Put(SwFmtAnchor(eAnchor));
180 nDrawXOfs2 = nDrawXOfs;
181 nDrawYOfs2 = nDrawYOfs;
183 if (eAnchor == FLY_AT_PARA)
185 if( SVBT8ToByte( pDo->bx ) == 1 ) // Pos: echt links
186 nDrawXOfs2 = static_cast< short >(nDrawXOfs2 - maSectionManager.GetPageLeft());
187 if( nInTable ) // Obj in Table
188 nDrawXOfs2 = nDrawXOfs2 - GetTableLeft(); // -> siehe Kommentar
189 // bei GetTableLeft()
191 else
193 if( SVBT8ToByte( pDo->bx ) != 1 )
194 nDrawXOfs2 = static_cast< short >(nDrawXOfs2 + maSectionManager.GetPageLeft());
197 return true;
200 // SetStdAttr() setzt die Attribute, die jedes Objekt hat
202 static void SetStdAttr( SfxItemSet& rSet, WW8_DP_LINETYPE& rL,
203 WW8_DP_SHADOW& rSh )
205 if( SVBT16ToShort( rL.lnps ) == 5 ){ // unsichtbar
206 rSet.Put( XLineStyleItem( XLINE_NONE ) );
207 }else{ // sichtbar
208 Color aCol( WW8TransCol( rL.lnpc ) ); // LinienFarbe
209 rSet.Put( XLineColorItem( aEmptyStr, aCol ) );
210 rSet.Put( XLineWidthItem( SVBT16ToShort( rL.lnpw ) ) );
211 // LinienDicke
212 if( SVBT16ToShort( rL.lnps ) >= 1
213 && SVBT16ToShort(rL.lnps ) <= 4 ){ // LinienStil
214 rSet.Put( XLineStyleItem( XLINE_DASH ) );
215 sal_Int16 nLen = SVBT16ToShort( rL.lnpw );
216 XDash aD( XDASH_RECT, 1, 2 * nLen, 1, 5 * nLen, 5 * nLen );
217 switch( SVBT16ToShort( rL.lnps ) ){
218 case 1: aD.SetDots( 0 ); // Dash
219 aD.SetDashLen( 6 * nLen );
220 aD.SetDistance( 4 * nLen );
221 break;
222 case 2: aD.SetDashes( 0 ); break; // Dot
223 case 3: break; // Dash Dot
224 case 4: aD.SetDots( 2 ); break; // Dash Dot Dot
226 rSet.Put( XLineDashItem( aEmptyStr, aD ) );
227 }else{
228 rSet.Put( XLineStyleItem( XLINE_SOLID ) ); // noetig fuer TextBox
231 if( SVBT16ToShort( rSh.shdwpi ) ){ // Schatten
232 rSet.Put(SdrShadowItem(true));
233 rSet.Put( SdrShadowXDistItem( SVBT16ToShort( rSh.xaOffset ) ) );
234 rSet.Put( SdrShadowYDistItem( SVBT16ToShort( rSh.yaOffset ) ) );
238 // SetFill setzt Fuellattribute wie Vordergrund- und Hintergrund-Farbe
239 // und Muster durch Reduktion auf eine Farbe.
240 // SetFill() setzt z.Zt kein Muster, da Sdr das nur sehr umstaendlich kann
241 // und die Sdr-Schraffur ( XDash ) noch nicht fertig ist.
242 // Statt dessen wird eine Mischfarbe gewaehlt, die auf den entsprechenden
243 // Farbton zwischen den Farben liegt.
245 static void SetFill( SfxItemSet& rSet, WW8_DP_FILL& rFill )
247 static sal_uInt8 nPatA[] =
249 0, 0, 5, 10, 20, 25, 30, 40, 50, 60, 70, 75, 80,
250 90, 50, 50, 50, 50, 50, 50, 33, 33, 33, 33, 33, 33
252 sal_uInt16 nPat = SVBT16ToShort(rFill.flpp);
254 if (nPat == 0) // transparent
255 rSet.Put(XFillStyleItem(XFILL_NONE));
256 else
258 rSet.Put(XFillStyleItem(XFILL_SOLID)); // necessary for textbox
259 if (nPat <= 1 || ((sizeof(nPatA)/sizeof(nPatA[0])) <= nPat))
261 // Solid Background or unknown
262 rSet.Put(XFillColorItem(aEmptyStr, WW8TransCol(rFill.dlpcBg)));
264 else
265 { // Brush -> Farbmischung
266 Color aB( WW8TransCol( rFill.dlpcBg ) );
267 Color aF( WW8TransCol( rFill.dlpcFg ) );
268 aB.SetRed( (sal_uInt8)( ( (sal_uLong)aF.GetRed() * nPatA[nPat]
269 + (sal_uLong)aB.GetRed() * ( 100 - nPatA[nPat] ) ) / 100 ) );
270 aB.SetGreen( (sal_uInt8)( ( (sal_uLong)aF.GetGreen() * nPatA[nPat]
271 + (sal_uLong)aB.GetGreen() * ( 100 - nPatA[nPat] ) ) / 100 ) );
272 aB.SetBlue( (sal_uInt8)( ( (sal_uLong)aF.GetBlue() * nPatA[nPat]
273 + (sal_uLong)aB.GetBlue() * ( 100 - nPatA[nPat] ) ) / 100 ) );
274 rSet.Put( XFillColorItem( aEmptyStr, aB ) );
279 static void SetLineEndAttr( SfxItemSet& rSet, WW8_DP_LINEEND& rLe,
280 WW8_DP_LINETYPE& rLt )
282 sal_uInt16 aSB = SVBT16ToShort( rLe.aStartBits );
283 if( aSB & 0x3 )
285 ::basegfx::B2DPolygon aPolygon;
286 aPolygon.append(::basegfx::B2DPoint(0.0, 330.0));
287 aPolygon.append(::basegfx::B2DPoint(100.0, 0.0));
288 aPolygon.append(::basegfx::B2DPoint(200.0, 330.0));
289 aPolygon.setClosed(true);
290 rSet.Put( XLineEndItem( aEmptyStr, ::basegfx::B2DPolyPolygon(aPolygon) ) );
291 sal_uInt16 nSiz = SVBT16ToShort( rLt.lnpw )
292 * ( ( aSB >> 2 & 0x3 ) + ( aSB >> 4 & 0x3 ) );
293 if( nSiz < 220 ) nSiz = 220;
294 rSet.Put(XLineEndWidthItem(nSiz));
295 rSet.Put(XLineEndCenterItem(false));
298 sal_uInt16 aEB = SVBT16ToShort( rLe.aEndBits );
299 if( aEB & 0x3 ){
300 ::basegfx::B2DPolygon aPolygon;
301 aPolygon.append(::basegfx::B2DPoint(0.0, 330.0));
302 aPolygon.append(::basegfx::B2DPoint(100.0, 0.0));
303 aPolygon.append(::basegfx::B2DPoint(200.0, 330.0));
304 aPolygon.setClosed(true);
305 rSet.Put( XLineStartItem( aEmptyStr, ::basegfx::B2DPolyPolygon(aPolygon) ) );
306 sal_uInt16 nSiz = SVBT16ToShort( rLt.lnpw )
307 * ( ( aEB >> 2 & 0x3 ) + ( aEB >> 4 & 0x3 ) );
308 if( nSiz < 220 ) nSiz = 220;
309 rSet.Put(XLineStartWidthItem(nSiz));
310 rSet.Put(XLineStartCenterItem(false));
314 // Ab hier folgen die Routinen fuer die einzelnen Objekte
315 SdrObject* SwWW8ImplReader::ReadLine( WW8_DPHEAD* pHd, const WW8_DO* pDo,
316 SfxAllItemSet &rSet)
318 WW8_DP_LINE aLine;
320 if( !ReadGrafStart( (void*)&aLine, sizeof( aLine ), pHd, pDo, rSet ) )
321 return 0;
323 Point aP[2];
325 Point& rP0 = aP[0];
326 Point& rP1 = aP[1];
328 rP0.X() = (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2;
329 rP0.Y() = (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2;
330 rP1 = rP0;
331 rP0.X() += (sal_Int16)SVBT16ToShort( aLine.xaStart );
332 rP0.Y() += (sal_Int16)SVBT16ToShort( aLine.yaStart );
333 rP1.X() += (sal_Int16)SVBT16ToShort( aLine.xaEnd );
334 rP1.Y() += (sal_Int16)SVBT16ToShort( aLine.yaEnd );
337 ::basegfx::B2DPolygon aPolygon;
338 aPolygon.append(::basegfx::B2DPoint(aP[0].X(), aP[0].Y()));
339 aPolygon.append(::basegfx::B2DPoint(aP[1].X(), aP[1].Y()));
340 SdrObject* pObj = new SdrPathObj(OBJ_LINE, ::basegfx::B2DPolyPolygon(aPolygon));
342 SetStdAttr( rSet, aLine.aLnt, aLine.aShd );
343 SetLineEndAttr( rSet, aLine.aEpp, aLine.aLnt );
345 return pObj;
348 SdrObject* SwWW8ImplReader::ReadRect( WW8_DPHEAD* pHd, const WW8_DO* pDo,
349 SfxAllItemSet &rSet)
351 WW8_DP_RECT aRect;
353 if( !ReadGrafStart( (void*)&aRect, sizeof( aRect ), pHd, pDo, rSet ) )
354 return 0;
356 Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
357 (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
358 Point aP1( aP0 );
359 aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
360 aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
362 SdrObject* pObj = new SdrRectObj( Rectangle( aP0, aP1 ) );
364 SetStdAttr( rSet, aRect.aLnt, aRect.aShd );
365 SetFill( rSet, aRect.aFill );
367 return pObj;
370 SdrObject* SwWW8ImplReader::ReadElipse( WW8_DPHEAD* pHd, const WW8_DO* pDo,
371 SfxAllItemSet &rSet)
373 WW8_DP_ELIPSE aElipse;
375 if( !ReadGrafStart( (void*)&aElipse, sizeof( aElipse ), pHd, pDo, rSet ) )
376 return 0;
378 Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
379 (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
380 Point aP1( aP0 );
381 aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
382 aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
384 SdrObject* pObj = new SdrCircObj( OBJ_CIRC, Rectangle( aP0, aP1 ) );
386 SetStdAttr( rSet, aElipse.aLnt, aElipse.aShd );
387 SetFill( rSet, aElipse.aFill );
389 return pObj;
392 SdrObject* SwWW8ImplReader::ReadArc( WW8_DPHEAD* pHd, const WW8_DO* pDo,
393 SfxAllItemSet &rSet)
395 WW8_DP_ARC aArc;
397 if( !ReadGrafStart( (void*)&aArc, sizeof( aArc ), pHd, pDo, rSet ) )
398 return 0;
400 Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
401 (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
402 Point aP1( aP0 );
403 aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa ) * 2;
404 aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya ) * 2;
406 short nA[] = { 2, 3, 1, 0 };
407 short nW = nA[ ( ( SVBT8ToByte( aArc.fLeft ) & 1 ) << 1 )
408 + ( SVBT8ToByte( aArc.fUp ) & 1 ) ];
409 if( !SVBT8ToByte( aArc.fLeft ) ){
410 aP0.Y() -= (sal_Int16)SVBT16ToShort( pHd->dya );
411 aP1.Y() -= (sal_Int16)SVBT16ToShort( pHd->dya );
413 if( SVBT8ToByte( aArc.fUp ) ){
414 aP0.X() -= (sal_Int16)SVBT16ToShort( pHd->dxa );
415 aP1.X() -= (sal_Int16)SVBT16ToShort( pHd->dxa );
418 SdrObject* pObj = new SdrCircObj( OBJ_SECT, Rectangle( aP0, aP1 ),
419 nW * 9000, ( ( nW + 1 ) & 3 ) * 9000 );
421 SetStdAttr( rSet, aArc.aLnt, aArc.aShd );
422 SetFill( rSet, aArc.aFill );
424 return pObj;
427 SdrObject* SwWW8ImplReader::ReadPolyLine( WW8_DPHEAD* pHd, const WW8_DO* pDo,
428 SfxAllItemSet &rSet)
430 WW8_DP_POLYLINE aPoly;
432 if( !ReadGrafStart( (void*)&aPoly, sizeof( aPoly ), pHd, pDo, rSet ) )
433 return 0;
435 sal_uInt16 nCount = SVBT16ToShort( aPoly.aBits1 ) >> 1 & 0x7fff;
436 boost::scoped_array<SVBT16> xP(new SVBT16[nCount * 2]);
438 bool bCouldRead = checkRead(*pStrm, xP.get(), nCount * 4); // Punkte einlesen
439 OSL_ENSURE(bCouldRead, "Short PolyLine header");
440 if (!bCouldRead)
441 return 0;
443 Polygon aP( nCount );
444 Point aPt;
445 for (sal_uInt16 i=0; i<nCount; ++i)
447 aPt.X() = SVBT16ToShort( xP[i << 1] ) + nDrawXOfs2
448 + (sal_Int16)SVBT16ToShort( pHd->xa );
449 aPt.Y() = SVBT16ToShort( xP[( i << 1 ) + 1] ) + nDrawYOfs2
450 + (sal_Int16)SVBT16ToShort( pHd->ya );
451 aP[i] = aPt;
453 xP.reset();
455 SdrObject* pObj = new SdrPathObj(( SVBT16ToShort( aPoly.aBits1 ) & 0x1 ) ? OBJ_POLY : OBJ_PLIN, ::basegfx::B2DPolyPolygon(aP.getB2DPolygon()));
456 SetStdAttr( rSet, aPoly.aLnt, aPoly.aShd );
457 SetFill( rSet, aPoly.aFill );
459 return pObj;
462 ESelection SwWW8ImplReader::GetESelection( long nCpStart, long nCpEnd )
464 sal_Int32 nPCnt = mpDrawEditEngine->GetParagraphCount();
465 sal_Int32 nSP = 0;
466 sal_Int32 nEP = 0;
467 while( (nSP < nPCnt)
468 && (nCpStart >= mpDrawEditEngine->GetTextLen( nSP ) + 1) )
470 nCpStart -= mpDrawEditEngine->GetTextLen( nSP ) + 1;
471 nSP++;
473 // Beim Ende erst 1 Zeichen spaeter auf naechste Zeile umschalten,
474 // da sonst Zeilenattribute immer eine Zeile zu weit reichen.
475 while( (nEP < nPCnt)
476 && (nCpEnd > mpDrawEditEngine->GetTextLen( nEP ) + 1) )
478 nCpEnd -= mpDrawEditEngine->GetTextLen( nEP ) + 1;
479 nEP++;
481 return ESelection( nSP, nCpStart, nEP, nCpEnd );
484 // InsertTxbxStyAttrs() setzt die Style-Attribute in den uebergebenen ItemSet.
485 // Es werden die SW-Styles genommen, die Import-WW-Styles sind zu diesem
486 // Zeitpunkt schon destruiert.
487 // Die SW-Styles werden per Tiefensuche, d.h. mit Parent-Styles nach den
488 // in aSrcTab angegebenen Attributen untersucht. Diese werden per Clone
489 // dupliziert, bei den Duplikaten werden die Which-IDs
490 // gemaess der Tabelle aDstTab umgesetzt, damit die EditEngine sie nicht
491 // ignoriert.
492 // Es werden hierbei sowohl Para- wie auch Zeichen-Attribute in den
493 // ItemSet gestopft.
494 void SwWW8ImplReader::InsertTxbxStyAttrs( SfxItemSet& rS, sal_uInt16 nColl )
496 SwWW8StyInf * pStyInf = GetStyle(nColl);
497 if( pStyInf != NULL && pStyInf->pFmt && pStyInf->bColl )
499 const SfxPoolItem* pItem;
500 for( sal_uInt16 i = POOLATTR_BEGIN; i < POOLATTR_END; i++ )
502 //If we are set in the source and not set in the destination
503 //then add it in.
504 if ( SFX_ITEM_SET == pStyInf->pFmt->GetItemState(
505 i, true, &pItem ) )
507 SfxItemPool *pEditPool = rS.GetPool();
508 sal_uInt16 nWhich = i;
509 sal_uInt16 nSlotId = rDoc.GetAttrPool().GetSlotId(nWhich);
510 if (
511 nSlotId && nWhich != nSlotId &&
512 0 != (nWhich = pEditPool->GetWhich(nSlotId)) &&
513 nWhich != nSlotId &&
514 ( SFX_ITEM_SET != rS.GetItemState(nWhich, false) )
517 SfxPoolItem* pCopy = pItem->Clone();
518 pCopy->SetWhich( nWhich );
519 rS.Put( *pCopy );
520 delete pCopy;
528 static void lcl_StripFields(String &rString, long &rNewStartCp)
530 for(sal_uInt16 i=0; i < rString.Len(); i++)
532 if( 0x13 == rString.GetChar( i ) )
536 rString.Erase( i, 1 );
537 rNewStartCp++;
539 while( rString.Len()
540 && ( i < rString.Len())
541 && (0x14 != rString.GetChar( i ) )
542 && (0x15 != rString.GetChar( i ) ) );
543 if( rString.Len() )
545 if( 0x14 == rString.GetChar( i ) )
547 rString.Erase( i, 1 );
548 rNewStartCp++;
551 i++;
553 while( rString.Len()
554 && ( i < rString.Len())
555 && (0x15 != rString.GetChar( i ) ) );
556 if( i < rString.Len() )
557 rString.Erase( i, 1 );
559 else if( 0x15 == rString.GetChar( i ) )
560 rString.Erase( i, 1 );
566 class Chunk
568 private:
569 String msURL;
570 long mnStartPos; //0x13
571 long mnEndPos; //0x15
572 public:
573 explicit Chunk(long nStart, const String &rURL)
574 : msURL(rURL), mnStartPos(nStart), mnEndPos(0) {}
575 Chunk(const Chunk &rChunk)
576 : msURL(rChunk.msURL), mnStartPos(rChunk.mnStartPos),
577 mnEndPos(rChunk.mnEndPos) {}
578 Chunk& operator=(const Chunk &rChunk)
580 msURL = rChunk.msURL;
581 mnStartPos = rChunk.mnStartPos;
582 mnEndPos = rChunk.mnEndPos;
583 return *this;
585 void SetEndPos(long nEnd) { mnEndPos = nEnd; }
586 long GetStartPos() const {return mnStartPos;}
587 long GetEndPos() const {return mnEndPos;}
588 const String &GetURL() const {return msURL;}
589 void Adjust(xub_StrLen nAdjust)
591 mnStartPos-=nAdjust;
592 mnEndPos-=nAdjust;
596 // InsertAttrsAsDrawingAttrs() setzt zwischen StartCp und EndCp die Attribute.
597 // Dabei werden Style-Attribute als harte Attribute, Absatz- und Zeichen-
598 // attribute gesetzt.
599 void SwWW8ImplReader::InsertAttrsAsDrawingAttrs(long nStartCp, long nEndCp,
600 ManTypes eType, bool bONLYnPicLocFc)
603 Save and create new plcxman for this drawing object, of the type that
604 will include the para end mark inside a paragraph property range, as
605 drawing boxes have real paragraph marks as part of their text, while
606 normal writer has separate nodes for each paragraph and so has no actual
607 paragraph mark as part of the paragraph text.
609 WW8ReaderSave aSave(this);
610 pPlcxMan = new WW8PLCFMan(pSBase, eType, nStartCp, true);
612 WW8_CP nStart = pPlcxMan->Where();
613 WW8_CP nNext, nEnd, nStartReplace=0;
615 bool bDoingSymbol = false;
616 sal_Unicode cReplaceSymbol = cSymbol;
618 SfxItemSet *pS = new SfxItemSet(mpDrawEditEngine->GetEmptyItemSet());
619 WW8PLCFManResult aRes;
621 std::deque<Chunk> aChunks;
623 //Here store stack location
624 size_t nCurrentCount = pCtrlStck->size();
625 while (nStart < nEndCp)
627 //nStart is the beginning of the attributes for this range, and
628 //may be before the text itself. So watch out for that
629 WW8_CP nTxtStart = nStart;
630 if (nTxtStart < nStartCp)
631 nTxtStart = nStartCp;
632 // get position of next SPRM
633 bool bStartAttr = pPlcxMan->Get(&aRes);
634 nAktColl = pPlcxMan->GetColl();
635 if (aRes.nSprmId)
637 if( bONLYnPicLocFc )
639 if ( (68 == aRes.nSprmId) || (0x6A03 == aRes.nSprmId) )
641 Read_PicLoc(aRes.nSprmId, aRes.pMemPos +
642 mpSprmParser->DistanceToData(aRes.nSprmId), 4);
643 // Ok, that's what we were looking for. Now let's get
644 // out of here!
645 break;
648 else if ( aRes.nSprmId && (
649 (eFTN > aRes.nSprmId) || (0x0800 <= aRes.nSprmId) ) )
651 //Here place them onto our usual stack and we will pop them
652 //off and convert them later
653 if (bStartAttr)
655 ImportSprm(aRes.pMemPos, aRes.nSprmId);
656 if (!bDoingSymbol && bSymbol == true)
658 bDoingSymbol = true;
659 nStartReplace = nTxtStart;
660 cReplaceSymbol = cSymbol;
663 else
665 EndSprm( aRes.nSprmId );
666 if (bSymbol == false && bDoingSymbol)
668 bDoingSymbol = false;
669 OUStringBuffer sTemp;
670 comphelper::string::padToLength(sTemp,
671 nTxtStart - nStartReplace, cReplaceSymbol);
672 mpDrawEditEngine->QuickInsertText(sTemp.makeStringAndClear(),
673 GetESelection(nStartReplace - nStartCp,
674 nTxtStart - nStartCp ) );
678 else if (aRes.nSprmId == eFLD)
680 if (bStartAttr)
682 size_t nCount = pCtrlStck->size();
683 if (maFieldStack.empty() && Read_Field(&aRes))
685 String sURL;
686 for (size_t nI = pCtrlStck->size(); nI > nCount; --nI)
688 const SfxPoolItem *pItem = ((*pCtrlStck)[nI-1]).pAttr;
689 sal_uInt16 nWhich = pItem->Which();
690 if (nWhich == RES_TXTATR_INETFMT)
692 const SwFmtINetFmt *pURL =
693 (const SwFmtINetFmt *)pItem;
694 sURL = pURL->GetValue();
696 pCtrlStck->DeleteAndDestroy(nI-1);
698 aChunks.push_back(Chunk(nStart, sURL));
701 else
703 if (!maFieldStack.empty() && End_Field())
704 aChunks.back().SetEndPos(nStart+1);
709 pPlcxMan->advance();
710 nNext = pPlcxMan->Where();
712 if( (nNext != nStart) && !bONLYnPicLocFc )
714 nEnd = ( nNext < nEndCp ) ? nNext : nEndCp;
715 SfxItemPool *pEditPool = pS->GetPool();
717 //Here read current properties and convert them into pS
718 //and put those attrs into the draw box if they can be converted
719 //to draw attributes
720 if (pCtrlStck->size() - nCurrentCount)
722 for (size_t i = nCurrentCount; i < pCtrlStck->size(); ++i)
724 const SfxPoolItem *pItem = ((*pCtrlStck)[i]).pAttr;
725 sal_uInt16 nWhich = pItem->Which();
726 if( nWhich < RES_FLTRATTR_BEGIN ||
727 nWhich >= RES_FLTRATTR_END )
729 sal_uInt16 nSlotId = rDoc.GetAttrPool().GetSlotId(nWhich);
730 if (
731 nSlotId && nWhich != nSlotId &&
732 0 != (nWhich = pEditPool->GetWhich(nSlotId)) &&
733 nWhich != nSlotId
736 SfxPoolItem* pCopy = pItem->Clone();
737 pCopy->SetWhich( nWhich );
738 pS->Put( *pCopy );
739 delete pCopy;
744 //Fill in the remainder from the style
745 InsertTxbxStyAttrs(*pS, nAktColl);
747 if( pS->Count() )
749 mpDrawEditEngine->QuickSetAttribs( *pS,
750 GetESelection( nTxtStart - nStartCp, nEnd - nStartCp ) );
751 delete pS;
752 pS = new SfxItemSet(mpDrawEditEngine->GetEmptyItemSet());
755 nStart = nNext;
757 delete pS;
759 //pop off as far as recorded location just in case there were some left
760 //unclosed
761 for (size_t nI = pCtrlStck->size(); nI > nCurrentCount; --nI)
762 pCtrlStck->DeleteAndDestroy(nI-1);
764 typedef std::deque<Chunk>::iterator myIter;
765 myIter aEnd = aChunks.end();
766 for (myIter aIter = aChunks.begin(); aIter != aEnd; ++aIter)
768 ESelection aSel(GetESelection(aIter->GetStartPos()-nStartCp,
769 aIter->GetEndPos()-nStartCp));
770 String aString(mpDrawEditEngine->GetText(aSel));
771 xub_StrLen nOrigLen = aString.Len();
772 long nDummy(0);
773 lcl_StripFields(aString, nDummy);
775 xub_StrLen nChanged;
776 if (aIter->GetURL().Len())
778 SvxURLField aURL(aIter->GetURL(), aString,
779 SVXURLFORMAT_APPDEFAULT);
780 mpDrawEditEngine->QuickInsertField(SvxFieldItem(aURL, EE_FEATURE_FIELD), aSel);
781 nChanged = nOrigLen - 1;
783 else
785 mpDrawEditEngine->QuickInsertText(aString, aSel);
786 nChanged = nOrigLen - aString.Len();
788 for (myIter aIter2 = aIter+1; aIter2 != aEnd; ++aIter2)
789 aIter2->Adjust(nChanged);
793 Don't worry about the new pPlcxMan, the restorer removes it when
794 replacing the current one with the old one.
796 aSave.Restore(this);
799 bool SwWW8ImplReader::GetTxbxTextSttEndCp(WW8_CP& rStartCp, WW8_CP& rEndCp,
800 sal_uInt16 nTxBxS, sal_uInt16 nSequence)
802 // rasch den TextBox-PLCF greifen
803 WW8PLCFspecial* pT = pPlcxMan ? pPlcxMan->GetTxbx() : 0;
804 if( !pT )
806 OSL_ENSURE( !this, "+Wo ist der Grafik-Text (1) ?" );
807 return false;
810 // ggfs. zuerst die richtige TextBox-Story finden
811 bool bCheckTextBoxStory = ( nTxBxS && pT->GetIMax() >= nTxBxS );
812 if( bCheckTextBoxStory )
813 pT->SetIdx( nTxBxS-1 );
815 // dann Start und Ende ermitteln
816 void* pT0;
817 if( !pT->Get( rStartCp, pT0 ) )
819 OSL_ENSURE( !this, "+Wo ist der Grafik-Text (2) ?" );
820 return false;
823 if( bCheckTextBoxStory )
825 bool bReusable = (0 != SVBT16ToShort( ((WW8_TXBXS*)pT0)->fReusable ));
826 while( bReusable )
828 pT->advance();
829 if( !pT->Get( rStartCp, pT0 ) )
831 OSL_ENSURE( !this, "+Wo ist der Grafik-Text (2-a) ?" );
832 return false;
834 bReusable = (0 != SVBT16ToShort( ((WW8_TXBXS*)pT0)->fReusable ));
837 pT->advance();
838 if( !pT->Get( rEndCp, pT0 ) )
840 OSL_ENSURE( !this, "+Wo ist der Grafik-Text (3) ?" );
841 return false;
844 // jetzt ggfs. die passende Page in der Break-Table finden
845 if( bCheckTextBoxStory )
847 // Sonderfall: gesamte(!) Kette soll ermittelt werden,
848 // dann sind wir hier schon fertig!
849 if( USHRT_MAX > nSequence )
851 long nMinStartCp = rStartCp;
852 long nMaxEndCp = rEndCp;
853 // rasch den TextBox-Break-Deskriptor-PLCF greifen
854 pT = pPlcxMan->GetTxbxBkd();
855 if (!pT) //It can occur on occasion, Caolan
856 return false;
858 // den ersten Eintrag fuer diese TextBox-Story finden
859 if( !pT->SeekPos( rStartCp ) )
861 OSL_ENSURE( !this, "+Wo ist der Grafik-Text (4) ?" );
862 return false;
864 // ggfs. entsprechende Anzahl Eintraege weitergehen
865 for (sal_uInt16 iSequence = 0; iSequence < nSequence; ++iSequence)
866 pT->advance();
867 // dann die tatsaechlichen Start und Ende ermitteln
868 if( (!pT->Get( rStartCp, pT0 ))
869 || ( nMinStartCp > rStartCp ) )
871 OSL_ENSURE( !this, "+Wo ist der Grafik-Text (5) ?" );
872 return false;
874 if( rStartCp >= nMaxEndCp )
875 rEndCp = rStartCp; // kein Error: leerer String!
876 else
878 pT->advance();
879 if ( (!pT->Get(rEndCp, pT0)) || (nMaxEndCp < rEndCp-1) )
881 OSL_ENSURE( !this, "+Wo ist der Grafik-Text (6) ?" );
882 return false;
884 rEndCp -= 1;
887 else
888 rEndCp -= 1;
890 else
891 rEndCp -= 1;
892 return true;
895 // TxbxText() holt aus WW-File den Text und gibt diesen und den Anfangs- und
896 // den um -2 (bzw. -1 bei Ver8) korrigierten End-Cp zurueck
897 bool SwWW8ImplReader::GetRangeAsDrawingString(String& rString, long nStartCp, long nEndCp, ManTypes eType)
899 WW8_CP nOffset = pWwFib->GetBaseCp(eType);
901 bool bOk = false;
902 OSL_ENSURE(nStartCp <= nEndCp, "+Wo ist der Grafik-Text (7) ?");
903 if (nStartCp == nEndCp)
904 rString.Erase(); // leerer String: durchaus denkbar!
905 else if (nStartCp < nEndCp)
907 // den Text einlesen: kann sich ueber mehrere Pieces erstrecken!!!
908 sal_uInt16 nLen = pSBase->WW8ReadString(*pStrm, rString,
909 nStartCp + nOffset, nEndCp - nStartCp, GetCurrentCharSet());
910 OSL_ENSURE(nLen, "+Wo ist der Grafik-Text (8) ?");
911 if (nLen)
913 bOk = true;
914 if( 0x0d == rString.GetChar(nLen - 1) )
915 rString.Erase(nLen - 1);
917 rString.SearchAndReplaceAll( 0xb, 0xa );
920 return bOk;
923 OutlinerParaObject* SwWW8ImplReader::ImportAsOutliner(String &rString, WW8_CP nStartCp, WW8_CP nEndCp, ManTypes eType)
925 OutlinerParaObject* pRet = 0;
927 if (GetRangeAsDrawingString( rString, nStartCp, nEndCp, eType ))
929 if (!mpDrawEditEngine)
930 mpDrawEditEngine = new EditEngine(0);
932 mpDrawEditEngine->SetText(rString);
933 InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType);
935 //Annotations typically begin with a (useless) 0x5
936 if ((eType == MAN_AND) && mpDrawEditEngine->GetTextLen())
938 ESelection aFirstChar(0, 0, 0, 1);
939 if (comphelper::string::equals(mpDrawEditEngine->GetText( aFirstChar ), 0x5))
940 mpDrawEditEngine->QuickDelete(aFirstChar);
943 EditTextObject* pTemporaryText = mpDrawEditEngine->CreateTextObject();
944 pRet = new OutlinerParaObject(*pTemporaryText);
945 pRet->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT );
946 delete pTemporaryText;
948 mpDrawEditEngine->SetText( aEmptyStr );
949 mpDrawEditEngine->SetParaAttribs(0, mpDrawEditEngine->GetEmptyItemSet());
951 //Strip out fields, leaving the result
952 long nDummy(0);
953 lcl_StripFields(rString, nDummy);
954 //Strip out word's special characters for the simple string
955 rString = comphelper::string::remove(rString, 0x1);
956 rString = comphelper::string::remove(rString, 0x5);
957 rString = comphelper::string::remove(rString, 0x8);
958 rString.SearchAndReplaceAllAscii("\007\007", OUString("\007\012"));
959 rString.SearchAndReplaceAll(0x7, ' ');
963 return pRet;
966 // InsertTxbxText() fuegt fuer TextBoxen und CaptionBoxen den Text
967 // und die Attribute ein
968 SwFrmFmt* SwWW8ImplReader::InsertTxbxText(SdrTextObj* pTextObj,
969 Size* pObjSiz, sal_uInt16 nTxBxS, sal_uInt16 nSequence, long nPosCp,
970 SwFrmFmt* pOldFlyFmt, bool bMakeSdrGrafObj, bool& rbEraseTextObj,
971 bool* pbTestTxbxContainsText, long* pnStartCp, long* pnEndCp,
972 bool* pbContainsGraphics, SvxMSDffImportRec* pRecord)
974 SwFrmFmt* pFlyFmt = 0;
975 sal_uLong nOld = pStrm->Tell();
977 ManTypes eType = pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX;
979 rbEraseTextObj = false;
981 String aString;
982 WW8_CP nStartCp, nEndCp;
983 bool bContainsGraphics = false;
984 bool bTextWasRead = GetTxbxTextSttEndCp( nStartCp, nEndCp, nTxBxS,
985 nSequence ) && GetRangeAsDrawingString( aString, nStartCp, nEndCp, eType );
987 if (!mpDrawEditEngine)
988 mpDrawEditEngine = new EditEngine(0);
989 if( pObjSiz )
990 mpDrawEditEngine->SetPaperSize( *pObjSiz );
992 String aOrigString(aString);
993 if( bTextWasRead )
995 long nNewStartCp = nStartCp;
996 lcl_StripFields(aString, nNewStartCp);
998 if (1 != aString.Len())
1000 if ( (STRING_NOTFOUND != aString.Search(0x1)) ||
1001 (STRING_NOTFOUND != aString.Search(0x8)) )
1003 bContainsGraphics = true;
1006 else // May be a single graphic or object
1008 bool bDone = true;
1009 switch( aString.GetChar(0) )
1011 case 0x1:
1012 if (!pbTestTxbxContainsText)
1014 WW8ReaderSave aSave(this, nNewStartCp -1);
1015 bool bOldEmbeddObj = bEmbeddObj;
1016 //bEmbedd Ordinarily would have been set by field
1017 //parse, but this is impossible here so...
1018 bEmbeddObj = true;
1020 // 1st look for OLE- or Graph-Indicator Sprms
1021 WW8PLCFx_Cp_FKP* pChp = pPlcxMan->GetChpPLCF();
1022 WW8PLCFxDesc aDesc;
1023 pChp->GetSprms( &aDesc );
1024 WW8SprmIter aSprmIter(aDesc.pMemPos, aDesc.nSprmsLen,
1025 *mpSprmParser);
1027 const sal_uInt8* pParams = aSprmIter.GetAktParams();
1028 for( int nLoop = 0; nLoop < 2; ++nLoop )
1030 while( aSprmIter.GetSprms()
1031 && (0 != (pParams = aSprmIter.GetAktParams())) )
1033 sal_uInt16 nAktId = aSprmIter.GetAktId();
1034 switch( nAktId )
1036 case 75:
1037 case 118:
1038 case 0x080A:
1039 case 0x0856:
1040 Read_Obj(nAktId, pParams, 1);
1041 break;
1042 case 68: // Read_Pic()
1043 case 0x6A03:
1044 case 0x680E:
1045 Read_PicLoc(nAktId, pParams, 1);
1046 break;
1048 aSprmIter.advance();
1051 if( !nLoop )
1053 pChp->GetPCDSprms( aDesc );
1054 aSprmIter.SetSprms( aDesc.pMemPos,
1055 aDesc.nSprmsLen );
1058 aSave.Restore(this);
1059 bEmbeddObj=bOldEmbeddObj;
1061 // then import either an OLE of a Graphic
1062 if( bObj )
1064 if( bMakeSdrGrafObj && pTextObj &&
1065 pTextObj->GetUpGroup() )
1067 // SdrOleObj/SdrGrafObj anstatt des
1068 // SdrTextObj in dessen Gruppe einsetzen
1070 Graphic aGraph;
1071 SdrObject* pNew = ImportOleBase(aGraph);
1073 if( !pNew )
1075 pNew = new SdrGrafObj;
1076 ((SdrGrafObj*)pNew)->SetGraphic(aGraph);
1079 GrafikCtor();
1081 pNew->SetModel( pDrawModel );
1082 pNew->SetLogicRect( pTextObj->GetCurrentBoundRect() );
1083 pNew->SetLayer( pTextObj->GetLayer() );
1085 pTextObj->GetUpGroup()->GetSubList()->
1086 ReplaceObject(pNew, pTextObj->GetOrdNum());
1088 else
1089 pFlyFmt = ImportOle();
1090 bObj = false;
1092 else
1094 InsertAttrsAsDrawingAttrs(nNewStartCp, nNewStartCp+1,
1095 eType, true);
1096 pFlyFmt = ImportGraf(bMakeSdrGrafObj ? pTextObj : 0,
1097 pOldFlyFmt);
1100 break;
1101 case 0x8:
1102 if ( (!pbTestTxbxContainsText) && (!bObj) )
1103 pFlyFmt = Read_GrafLayer( nPosCp );
1104 break;
1105 default:
1106 bDone = false;
1107 break;
1110 if( bDone )
1112 if( pFlyFmt )
1114 if( pRecord )
1116 SfxItemSet aFlySet( rDoc.GetAttrPool(),
1117 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
1119 Rectangle aInnerDist( pRecord->nDxTextLeft,
1120 pRecord->nDyTextTop,
1121 pRecord->nDxTextRight,
1122 pRecord->nDyTextBottom );
1123 MatchSdrItemsIntoFlySet( pTextObj,
1124 aFlySet,
1125 pRecord->eLineStyle,
1126 pRecord->eLineDashing,
1127 pRecord->eShapeType,
1128 aInnerDist );
1130 pFlyFmt->SetFmtAttr( aFlySet );
1132 MapWrapIntoFlyFmt(pRecord, pFlyFmt);
1135 aString.Erase();
1136 rbEraseTextObj = (0 != pFlyFmt);
1141 if( pnStartCp )
1142 *pnStartCp = nStartCp;
1143 if( pnEndCp )
1144 *pnEndCp = nEndCp;
1146 if( pbTestTxbxContainsText )
1147 *pbTestTxbxContainsText = bTextWasRead && ! rbEraseTextObj;
1148 else if( !rbEraseTextObj )
1150 if( bTextWasRead )
1152 mpDrawEditEngine->SetText(aOrigString);
1153 InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType);
1156 bool bVertical = pTextObj->IsVerticalWriting() ? true : false;
1157 EditTextObject* pTemporaryText = mpDrawEditEngine->CreateTextObject();
1158 OutlinerParaObject* pOp = new OutlinerParaObject(*pTemporaryText);
1159 pOp->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT );
1160 pOp->SetVertical( bVertical );
1161 delete pTemporaryText;
1162 pTextObj->NbcSetOutlinerParaObject( pOp );
1163 pTextObj->SetVerticalWriting(bVertical);
1165 // Fuer die naechste Textbox noch die alten Absatz-Attribute
1166 // und Styles entfernen, sonst startet die naechste Box
1167 // mit falschen Attributen.
1168 // Vorgehen: Text loeschen = auf 1 Absatz reduzieren
1169 // und an diesem Absatz die Absatzattribute und Styles loeschen
1170 // (Empfehlung JOE)
1171 mpDrawEditEngine->SetText( aEmptyStr );
1172 mpDrawEditEngine->SetParaAttribs(0, mpDrawEditEngine->GetEmptyItemSet());
1175 pStrm->Seek( nOld );
1176 if (pbContainsGraphics)
1177 *pbContainsGraphics = bContainsGraphics;
1178 return pFlyFmt;
1182 bool SwWW8ImplReader::TxbxChainContainsRealText(sal_uInt16 nTxBxS, long& rStartCp,
1183 long& rEndCp)
1185 bool bErase, bContainsText;
1186 InsertTxbxText( 0,0,nTxBxS,USHRT_MAX,0,0,0, bErase, &bContainsText,
1187 &rStartCp, &rEndCp );
1188 return bContainsText;
1192 // TextBoxes only for Ver67 !!
1193 SdrObject* SwWW8ImplReader::ReadTxtBox( WW8_DPHEAD* pHd, const WW8_DO* pDo,
1194 SfxAllItemSet &rSet)
1196 bool bDummy;
1197 WW8_DP_TXTBOX aTxtB;
1199 if( !ReadGrafStart( (void*)&aTxtB, sizeof( aTxtB ), pHd, pDo, rSet ) )
1200 return 0;
1202 Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
1203 (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
1204 Point aP1( aP0 );
1205 aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
1206 aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
1208 SdrObject* pObj = new SdrRectObj( OBJ_TEXT, Rectangle( aP0, aP1 ) );
1209 pObj->SetModel( pDrawModel );
1210 pObj->NbcSetSnapRect(Rectangle(aP0, aP1));
1211 Size aSize( (sal_Int16)SVBT16ToShort( pHd->dxa ) ,
1212 (sal_Int16)SVBT16ToShort( pHd->dya ) );
1214 long nStartCpFly,nEndCpFly;
1215 bool bContainsGraphics;
1216 InsertTxbxText(PTR_CAST(SdrTextObj,pObj), &aSize, 0, 0, 0, 0, false,
1217 bDummy,0,&nStartCpFly,&nEndCpFly,&bContainsGraphics);
1219 SetStdAttr( rSet, aTxtB.aLnt, aTxtB.aShd );
1220 SetFill( rSet, aTxtB.aFill );
1222 rSet.Put( SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE ) );
1223 rSet.Put( SdrTextAutoGrowWidthItem(false));
1224 rSet.Put( SdrTextAutoGrowHeightItem(false));
1225 rSet.Put( SdrTextLeftDistItem( MIN_BORDER_DIST*2 ) );
1226 rSet.Put( SdrTextRightDistItem( MIN_BORDER_DIST*2 ) );
1227 rSet.Put( SdrTextUpperDistItem( MIN_BORDER_DIST ) );
1228 rSet.Put( SdrTextLowerDistItem( MIN_BORDER_DIST ) );
1230 return pObj;
1233 SdrObject* SwWW8ImplReader::ReadCaptionBox( WW8_DPHEAD* pHd, const WW8_DO* pDo,
1234 SfxAllItemSet &rSet)
1236 static SdrCaptionType aCaptA[] = { SDRCAPT_TYPE1, SDRCAPT_TYPE2,
1237 SDRCAPT_TYPE3, SDRCAPT_TYPE4 };
1239 WW8_DP_CALLOUT_TXTBOX aCallB;
1241 if( !ReadGrafStart( (void*)&aCallB, sizeof( aCallB ), pHd, pDo, rSet ) )
1242 return 0;
1244 sal_uInt16 nCount = SVBT16ToShort( aCallB.dpPolyLine.aBits1 ) >> 1 & 0x7fff;
1245 boost::scoped_array<SVBT16> xP(new SVBT16[nCount * 2]);
1247 bool bCouldRead = checkRead(*pStrm, xP.get(), nCount * 4); // Punkte einlesen
1248 OSL_ENSURE(bCouldRead, "Short CaptionBox header");
1249 if (!bCouldRead)
1250 return 0;
1252 sal_uInt8 nTyp = (sal_uInt8)nCount - 1;
1253 if( nTyp == 1 && SVBT16ToShort( xP[0] ) == SVBT16ToShort( xP[2] ) )
1254 nTyp = 0;
1256 Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) +
1257 (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.xa ) + nDrawXOfs2,
1258 (sal_Int16)SVBT16ToShort( pHd->ya )
1259 + (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.ya ) + nDrawYOfs2 );
1260 Point aP1( aP0 );
1261 aP1.X() += (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dxa );
1262 aP1.Y() += (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dya );
1263 Point aP2( (sal_Int16)SVBT16ToShort( pHd->xa )
1264 + (sal_Int16)SVBT16ToShort( aCallB.dpheadPolyLine.xa )
1265 + nDrawXOfs2 + (sal_Int16)SVBT16ToShort( xP[0] ),
1266 (sal_Int16)SVBT16ToShort( pHd->ya )
1267 + (sal_Int16)SVBT16ToShort( aCallB.dpheadPolyLine.ya )
1268 + nDrawYOfs2 + (sal_Int16)SVBT16ToShort( xP[1] ) );
1269 xP.reset();
1271 SdrCaptionObj* pObj = new SdrCaptionObj( Rectangle( aP0, aP1 ), aP2 );
1272 pObj->SetModel( pDrawModel );
1273 pObj->NbcSetSnapRect(Rectangle(aP0, aP1));
1274 Size aSize( (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dxa ),
1275 (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dya ) );
1276 bool bEraseThisObject;
1278 InsertTxbxText(pObj, &aSize, 0, 0, 0, 0, false, bEraseThisObject );
1280 if( SVBT16ToShort( aCallB.dptxbx.aLnt.lnps ) != 5 ) // Umrandung sichtbar ?
1281 SetStdAttr( rSet, aCallB.dptxbx.aLnt, aCallB.dptxbx.aShd );
1282 else // nein -> Nimm Linie
1283 SetStdAttr( rSet, aCallB.dpPolyLine.aLnt, aCallB.dptxbx.aShd );
1284 SetFill( rSet, aCallB.dptxbx.aFill );
1285 rSet.Put( SdrCaptionTypeItem( aCaptA[nTyp] ) );
1287 return pObj;
1291 SdrObject *SwWW8ImplReader::ReadGroup( WW8_DPHEAD* pHd, const WW8_DO* pDo,
1292 SfxAllItemSet &rSet)
1294 sal_Int16 nGrouped;
1296 if( !ReadGrafStart( (void*)&nGrouped, sizeof( nGrouped ), pHd, pDo, rSet ) )
1297 return 0;
1299 #ifdef OSL_BIGENDIAN
1300 nGrouped = (sal_Int16)OSL_SWAPWORD( nGrouped );
1301 #endif
1303 nDrawXOfs = nDrawXOfs + (sal_Int16)SVBT16ToShort( pHd->xa );
1304 nDrawYOfs = nDrawYOfs + (sal_Int16)SVBT16ToShort( pHd->ya );
1306 SdrObject* pObj = new SdrObjGroup;
1308 short nLeft = (sal_Int16)SVBT16ToShort( pHd->cb ) - sizeof( WW8_DPHEAD );
1309 for (int i = 0; i < nGrouped; i++)
1311 SfxAllItemSet aSet(pDrawModel->GetItemPool());
1312 if (SdrObject *pObject = ReadGrafPrimitive(nLeft, pDo, aSet))
1314 // first add and then set ItemSet
1315 SdrObjList *pSubGroup = pObj->GetSubList();
1316 OSL_ENSURE(pSubGroup, "Why no sublist available?");
1317 if (pSubGroup)
1318 pSubGroup->InsertObject(pObject, 0);
1319 pObject->SetMergedItemSetAndBroadcast(aSet);
1323 nDrawXOfs = nDrawXOfs - (sal_Int16)SVBT16ToShort( pHd->xa );
1324 nDrawYOfs = nDrawYOfs - (sal_Int16)SVBT16ToShort( pHd->ya );
1326 return pObj;
1329 SdrObject* SwWW8ImplReader::ReadGrafPrimitive( short& rLeft, const WW8_DO* pDo,
1330 SfxAllItemSet &rSet)
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 bool bCouldRead = checkRead(*pStrm, &aHd, sizeof(WW8_DPHEAD));
1337 OSL_ENSURE(bCouldRead, "Graphic Primitive header short read" );
1338 if (!bCouldRead)
1340 rLeft=0;
1341 return pRet;
1344 if( rLeft >= SVBT16ToShort(aHd.cb) ) // Vorsichtsmassmahme
1346 rSet.Put(SwFmtSurround(SURROUND_THROUGHT));
1347 switch (SVBT16ToShort(aHd.dpk) & 0xff )
1349 case 0:
1350 pRet = ReadGroup( &aHd, pDo, rSet );
1351 break;
1352 case 1:
1353 pRet = ReadLine( &aHd, pDo, rSet );
1354 break;
1355 case 2:
1356 pRet = ReadTxtBox( &aHd, pDo, rSet );
1357 break;
1358 case 3:
1359 pRet = ReadRect( &aHd, pDo, rSet );
1360 break;
1361 case 4:
1362 pRet = ReadElipse( &aHd, pDo, rSet );
1363 break;
1364 case 5:
1365 pRet = ReadArc( &aHd, pDo, rSet );
1366 break;
1367 case 6:
1368 pRet = ReadPolyLine( &aHd, pDo, rSet );
1369 break;
1370 case 7:
1371 pRet = ReadCaptionBox( &aHd, pDo, rSet );
1372 break;
1373 default: // unbekannt
1374 pStrm->SeekRel(SVBT16ToShort(aHd.cb) - sizeof(WW8_DPHEAD));
1375 break;
1378 else
1380 OSL_ENSURE( !this, "+Grafik-Overlap" );
1382 rLeft = rLeft - SVBT16ToShort( aHd.cb );
1383 return pRet;
1386 void SwWW8ImplReader::ReadGrafLayer1( WW8PLCFspecial* pPF, long nGrafAnchorCp )
1388 pPF->SeekPos( nGrafAnchorCp );
1389 WW8_FC nStartFc;
1390 void* pF0;
1391 if( !pPF->Get( nStartFc, pF0 ) )
1393 OSL_ENSURE( !this, "+Wo ist die Grafik (2) ?" );
1394 return;
1396 WW8_FDOA* pF = (WW8_FDOA*)pF0;
1397 if( !SVBT32ToUInt32( pF->fc ) )
1399 OSL_ENSURE( !this, "+Wo ist die Grafik (3) ?" );
1400 return;
1403 bool bCouldSeek = checkSeek(*pStrm, SVBT32ToUInt32(pF->fc));
1404 OSL_ENSURE(bCouldSeek, "Invalid Graphic offset");
1405 if (!bCouldSeek)
1406 return;
1408 // Lese Draw-Header
1409 WW8_DO aDo;
1410 bool bCouldRead = checkRead(*pStrm, &aDo, sizeof(WW8_DO));
1411 OSL_ENSURE(bCouldRead, "Short Graphic header");
1412 if (!bCouldRead)
1413 return;
1415 short nLeft = SVBT16ToShort( aDo.cb ) - sizeof( WW8_DO );
1416 while (nLeft > static_cast<short>(sizeof(WW8_DPHEAD)))
1418 SfxAllItemSet aSet( pDrawModel->GetItemPool() );
1419 if (SdrObject *pObject = ReadGrafPrimitive( nLeft, &aDo, aSet ))
1421 pWWZOrder->InsertDrawingObject(pObject, SVBT16ToShort(aDo.dhgt));
1422 SwFrmFmt *pFrm = rDoc.Insert( *pPaM, *pObject, &aSet, NULL);
1423 pObject->SetMergedItemSet(aSet);
1424 pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFrm);
1429 sal_Int32 SwMSDffManager::GetEscherLineMatch(MSO_LineStyle eStyle,
1430 MSO_SPT eShapeType, sal_Int32 &rThick)
1432 sal_Int32 nOutsideThick = 0;
1434 Beachte: im Gegensatz zu den Winword-ueblichen Tabellen- und
1435 Rahmen-Randbreiten-Angaben, bei denen jeweils aus der Staerke *einer*
1436 Linie die Gesamt-Randbreite zu errechnen ist, liegen die aus dem ESCHER
1437 stammenden Daten bereits als Gesamt-Breite [twips] vor!
1439 Der Winword default ist 15 tw. Wir nehmen hierfuer unsere 20 tw Linie. (
1440 0.75 pt uns 1.0 pt sehen sich auf dem Ausdruck naemlich aehnlicher als
1441 etwas 0.75 pt und unsere 0.05 pt Haarlinie. ) Die Haarlinie setzen wir nur
1442 bei Winword-Staerken bis zu maximal 0.5 pt ein.
1444 switch( eStyle )
1446 case mso_lineTriple:
1447 case mso_lineSimple:
1448 nOutsideThick = eShapeType != mso_sptTextBox ? rThick : rThick/2;
1449 break;
1450 case mso_lineDouble:
1451 if (eShapeType == mso_sptTextBox)
1453 nOutsideThick = rThick/6;
1454 rThick = rThick*2/3;
1456 else
1457 nOutsideThick = rThick*2/3;
1458 break;
1459 case mso_lineThickThin:
1460 if (eShapeType == mso_sptTextBox)
1462 nOutsideThick = rThick*3/10;
1463 rThick = rThick*4/5;
1465 else
1466 nOutsideThick = rThick*4/5;
1467 break;
1468 case mso_lineThinThick:
1470 if (eShapeType == mso_sptTextBox)
1472 nOutsideThick = rThick/10;
1473 rThick = rThick*3/5;
1475 else
1476 nOutsideThick = rThick*3/5;
1478 break;
1479 default:
1480 break;
1482 return nOutsideThick;
1485 //Returns the thickness of the line outside the frame, the logic of
1486 //words positioning of borders around floating objects is that of a
1487 //disturbed mind.
1488 sal_Int32 SwWW8ImplReader::MatchSdrBoxIntoFlyBoxItem(const Color& rLineColor,
1489 MSO_LineStyle eLineStyle, MSO_LineDashing eDashing, MSO_SPT eShapeType, sal_Int32 &rLineThick,
1490 SvxBoxItem& rBox )
1492 sal_Int32 nOutsideThick = 0;
1493 if( !rLineThick )
1494 return nOutsideThick;
1496 ::editeng::SvxBorderStyle nIdx = table::BorderLineStyle::NONE;
1498 sal_Int32 nLineThick=rLineThick;
1499 nOutsideThick = SwMSDffManager::GetEscherLineMatch(eLineStyle,
1500 eShapeType, rLineThick);
1503 Beachte: im Gegensatz zu den Winword-ueblichen Tabellen- und
1504 Rahmen-Randbreiten-Angaben, bei denen jeweils aus der Staerke *einer*
1505 Linie die Gesamt-Randbreite zu errechnen ist, liegen die aus dem ESCHER
1506 stammenden Daten bereits als Gesamt-Breite [twips] vor!
1508 Der Winword default ist 15 tw. Wir nehmen hierfuer unsere 20 tw Linie. (
1509 0.75 pt uns 1.0 pt sehen sich auf dem Ausdruck naemlich aehnlicher als
1510 etwas 0.75 pt und unsere 0.05 pt Haarlinie. ) Die Haarlinie setzen wir nur
1511 bei Winword-Staerken bis zu maximal 0.5 pt ein.
1513 switch( +eLineStyle )
1515 // zuerst die Einzel-Linien
1516 case mso_lineSimple:
1517 nIdx = table::BorderLineStyle::SOLID;
1518 break;
1519 // dann die Doppel-Linien, fuer die wir feine Entsprechungen haben :-)))
1520 case mso_lineDouble:
1521 nIdx = table::BorderLineStyle::DOUBLE;
1522 break;
1523 case mso_lineThickThin:
1524 nIdx = table::BorderLineStyle::THICKTHIN_SMALLGAP;
1525 break;
1526 case mso_lineThinThick:
1527 nIdx = table::BorderLineStyle::THINTHICK_SMALLGAP;
1528 break;
1529 // We have no triple border, use double instead.
1530 case mso_lineTriple:
1531 nIdx = table::BorderLineStyle::DOUBLE;
1532 break;
1533 // no line style is set
1534 case (MSO_LineStyle)USHRT_MAX:
1535 break;
1536 // erroneously not implemented line style is set
1537 default:
1538 OSL_ENSURE(!this, "eLineStyle is not (yet) implemented!");
1539 break;
1542 switch( eDashing )
1544 case mso_lineDashGEL:
1545 nIdx = table::BorderLineStyle::DASHED;
1546 break;
1547 case mso_lineDotGEL:
1548 nIdx = table::BorderLineStyle::DOTTED;
1549 break;
1550 default:
1551 break;
1554 if (table::BorderLineStyle::NONE != nIdx)
1556 SvxBorderLine aLine;
1557 aLine.SetColor( rLineColor );
1559 aLine.SetWidth( nLineThick ); // No conversion here, nLineThick is already in twips
1560 aLine.SetBorderLineStyle(nIdx);
1562 for(sal_uInt16 nLine = 0; nLine < 4; ++nLine)
1564 //aLine is cloned by SetLine
1565 rBox.SetLine(&aLine, nLine);
1569 return nOutsideThick;
1572 #define WW8ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue()
1574 void SwWW8ImplReader::MatchSdrItemsIntoFlySet( SdrObject* pSdrObj,
1575 SfxItemSet& rFlySet, MSO_LineStyle eLineStyle, MSO_LineDashing eDashing, MSO_SPT eShapeType,
1576 Rectangle& rInnerDist )
1579 am Rahmen zu setzende Frame-Attribute
1580 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1581 SwFmtFrmSize falls noch nicht gesetzt, hier setzen
1582 SvxLRSpaceItem hier setzen
1583 SvxULSpaceItem hier setzen
1584 SvxOpaqueItem (Derzeit bei Rahmen nicht moeglich! khz 10.2.1999)
1585 SwFmtSurround bereits gesetzt
1586 SwFmtVertOrient bereits gesetzt
1587 SwFmtHoriOrient bereits gesetzt
1588 SwFmtAnchor bereits gesetzt
1589 SvxBoxItem hier setzen
1590 SvxBrushItem hier setzen
1591 SvxShadowItem hier setzen
1594 // 1. GrafikObjekt des Docs?
1595 GrafikCtor();
1597 const SfxItemSet& rOldSet = pSdrObj->GetMergedItemSet();
1599 // einige Items koennen direkt so uebernommen werden
1600 const sal_uInt16 nDirectMatch = 2;
1601 static RES_FRMATR const aDirectMatch[ nDirectMatch ] =
1603 RES_LR_SPACE, // Aussenabstand links/rechts: SvxLRSpaceItem
1604 RES_UL_SPACE // Aussenabstand Oben/unten: SvxULSpaceItem
1606 const SfxPoolItem* pPoolItem;
1607 for(sal_uInt16 nItem = 0; nItem < nDirectMatch; ++nItem)
1608 if( SFX_ITEM_SET == rOldSet.GetItemState(
1609 static_cast< sal_uInt16 >(aDirectMatch[ nItem ]), false, &pPoolItem) )
1611 rFlySet.Put( *pPoolItem );
1615 // jetzt die Umrandung berechnen und die Box bauen: Das Mass wird fuer die
1616 // Rahmen-GROESSE benoetigt!
1617 SvxBoxItem aBox(sw::util::ItemGet<SvxBoxItem>(rFlySet, RES_BOX));
1618 // dashed oder solid wird zu solid
1619 // WW-default: 0.75 pt = 15 twips
1620 sal_Int32 nLineThick = 15, nOutside=0;
1622 // check if LineStyle is *really* set!
1623 const SfxPoolItem* pItem;
1625 SfxItemState eState = rOldSet.GetItemState(XATTR_LINESTYLE,true,&pItem);
1626 if( eState == SFX_ITEM_SET )
1628 // Now, that we know there is a line style we will make use the
1629 // parameter given to us when calling the method... :-)
1630 const Color aLineColor = static_cast< XLineColorItem const & >(
1631 rOldSet.Get(XATTR_LINECOLOR)).GetColorValue();
1632 nLineThick = WW8ITEMVALUE(rOldSet, XATTR_LINEWIDTH, XLineWidthItem);
1634 if( !nLineThick )
1635 nLineThick = 1; // for Writer, zero is "no border", so set a minimal value
1637 nOutside = MatchSdrBoxIntoFlyBoxItem(aLineColor, eLineStyle,
1638 eDashing, eShapeType, nLineThick, aBox);
1641 rInnerDist.Left()+=nLineThick;
1642 rInnerDist.Top()+=nLineThick;
1643 rInnerDist.Right()+=nLineThick;
1644 rInnerDist.Bottom()+=nLineThick;
1646 const SvxBorderLine *pLine;
1647 if (0 != (pLine = aBox.GetLine(BOX_LINE_LEFT)))
1649 rInnerDist.Left() -= (pLine->GetScaledWidth());
1652 if (0 != (pLine = aBox.GetLine(BOX_LINE_TOP)))
1654 rInnerDist.Top() -= (pLine->GetScaledWidth());
1657 if (0 != (pLine = aBox.GetLine(BOX_LINE_RIGHT)))
1659 rInnerDist.Right() -= (pLine->GetScaledWidth());
1662 if (0 != (pLine = aBox.GetLine(BOX_LINE_BOTTOM)))
1664 rInnerDist.Bottom() -= (pLine->GetScaledWidth());
1667 // set distances from box's border to text contained within the box
1668 if( 0 < rInnerDist.Left() )
1669 aBox.SetDistance( (sal_uInt16)rInnerDist.Left(), BOX_LINE_LEFT );
1670 if( 0 < rInnerDist.Top() )
1671 aBox.SetDistance( (sal_uInt16)rInnerDist.Top(), BOX_LINE_TOP );
1672 if( 0 < rInnerDist.Right() )
1673 aBox.SetDistance( (sal_uInt16)rInnerDist.Right(), BOX_LINE_RIGHT );
1674 if( 0 < rInnerDist.Bottom() )
1675 aBox.SetDistance( (sal_uInt16)rInnerDist.Bottom(), BOX_LINE_BOTTOM );
1677 bool bFixSize = !(WW8ITEMVALUE(rOldSet, SDRATTR_TEXT_AUTOGROWHEIGHT,
1678 SdrTextAutoGrowHeightItem));
1680 // Size: SwFmtFrmSize
1681 if( SFX_ITEM_SET != rFlySet.GetItemState(RES_FRM_SIZE, false) )
1683 const Rectangle& rSnapRect = pSdrObj->GetSnapRect();
1684 // if necessary adapt width and position of the framework: The
1685 // recorded interior is to remain equally large despite thick edges.
1686 rFlySet.Put( SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE,
1687 rSnapRect.GetWidth() + 2*nOutside,
1688 rSnapRect.GetHeight() + 2*nOutside) );
1690 else //If a size is set, adjust it to consider border thickness
1692 SwFmtFrmSize aSize = (const SwFmtFrmSize &)(rFlySet.Get(RES_FRM_SIZE));
1694 SwFmtFrmSize aNewSize = SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE,
1695 aSize.GetWidth() + 2*nOutside,
1696 aSize.GetHeight() + 2*nOutside);
1697 aNewSize.SetWidthSizeType(aSize.GetWidthSizeType());
1698 rFlySet.Put( aNewSize );
1701 //Sadly word puts escher borders outside the graphic, but orients the
1702 //graphic in relation to the top left inside the border. We don't
1703 if (nOutside)
1705 SwFmtHoriOrient aHori = (const SwFmtHoriOrient &)(rFlySet.Get(
1706 RES_HORI_ORIENT));
1707 aHori.SetPos(MakeSafePositioningValue(aHori.GetPos()-nOutside));
1708 rFlySet.Put(aHori);
1710 SwFmtVertOrient aVert = (const SwFmtVertOrient &)(rFlySet.Get(
1711 RES_VERT_ORIENT));
1712 aVert.SetPos(aVert.GetPos()-nOutside);
1713 rFlySet.Put(aVert);
1716 // jetzt die Umrandung setzen
1717 rFlySet.Put( aBox );
1719 // Schattenwurf der Box: SvxShadowItem
1720 if( WW8ITEMVALUE(rOldSet, SDRATTR_SHADOW, SdrShadowItem) )
1722 SvxShadowItem aShadow( RES_SHADOW );
1724 const Color aShdColor = static_cast< SdrShadowColorItem const & >(
1725 rOldSet.Get(SDRATTR_SHADOWCOLOR)).GetColorValue();
1726 const sal_Int32 nShdDistX = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWXDIST,
1727 SdrShadowXDistItem);
1728 const sal_Int32 nShdDistY = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWYDIST,
1729 SdrShadowYDistItem);
1731 aShadow.SetColor( Color( aShdColor ) );
1733 aShadow.SetWidth(writer_cast<sal_uInt16>((std::abs( nShdDistX) +
1734 std::abs( nShdDistY )) / 2 ));
1736 SvxShadowLocation eShdPosi;
1737 if( 0 <= nShdDistX )
1739 if( 0 <= nShdDistY )
1740 eShdPosi = SVX_SHADOW_BOTTOMRIGHT;
1741 else
1742 eShdPosi = SVX_SHADOW_TOPRIGHT;
1744 else
1746 if( 0 <= nShdDistY )
1747 eShdPosi = SVX_SHADOW_BOTTOMLEFT;
1748 else
1749 eShdPosi = SVX_SHADOW_TOPLEFT;
1751 aShadow.SetLocation( eShdPosi );
1753 rFlySet.Put( aShadow );
1755 Color Temp(COL_WHITE);
1756 SvxBrushItem aBrushItem(Temp, RES_BACKGROUND);
1757 bool bBrushItemOk = false;
1758 sal_uInt8 nTrans = 0;
1760 //Separate transparency
1761 eState = rOldSet.GetItemState(XATTR_FILLTRANSPARENCE, true, &pItem);
1762 if (eState == SFX_ITEM_SET)
1764 sal_uInt16 nRes = WW8ITEMVALUE(rOldSet, XATTR_FILLTRANSPARENCE,
1765 XFillTransparenceItem);
1766 nTrans = sal_uInt8((nRes * 0xFE) / 100);
1767 aBrushItem.GetColor().SetTransparency(nTrans);
1768 bBrushItemOk = true;
1771 // Hintergrund: SvxBrushItem
1772 eState = rOldSet.GetItemState(XATTR_FILLSTYLE, true, &pItem);
1773 if (eState == SFX_ITEM_SET)
1775 const XFillStyle eFill = ((const XFillStyleItem*)pItem)->GetValue();
1777 switch (eFill)
1779 case XFILL_NONE:
1780 //Writer graphics don't have it yet
1781 if (eShapeType != mso_sptPictureFrame)
1783 aBrushItem.GetColor().SetTransparency(0xFE);
1784 bBrushItemOk = true;
1786 break;
1787 case XFILL_SOLID:
1788 case XFILL_GRADIENT:
1790 const Color aColor = static_cast< XFillColorItem const & >(
1791 rOldSet.Get(XATTR_FILLCOLOR)).GetColorValue();
1792 aBrushItem.SetColor(aColor);
1794 if (bBrushItemOk) //has trans
1795 aBrushItem.GetColor().SetTransparency(nTrans);
1797 bBrushItemOk = true;
1799 break;
1800 //case XFILL_GRADIENT:
1801 //break;
1802 case XFILL_HATCH:
1803 break;
1804 case XFILL_BITMAP:
1806 GraphicObject aGrfObj(static_cast< XFillBitmapItem const & >(rOldSet.Get(XATTR_FILLBITMAP)).GetGraphicObject());
1807 const bool bTile(WW8ITEMVALUE(rOldSet, XATTR_FILLBMP_TILE, SfxBoolItem) ? true: false);
1809 if(bBrushItemOk) //has trans
1811 GraphicAttr aAttr(aGrfObj.GetAttr());
1813 aAttr.SetTransparency(nTrans);
1814 aGrfObj.SetAttr(aAttr);
1817 aBrushItem.SetGraphicObject(aGrfObj);
1818 aBrushItem.SetGraphicPos(bTile ? GPOS_TILED : GPOS_AREA);
1819 bBrushItemOk = true;
1821 break;
1825 if (bBrushItemOk)
1826 rFlySet.Put(aBrushItem, RES_BACKGROUND);
1829 void SwWW8ImplReader::AdjustLRWrapForWordMargins(
1830 const SvxMSDffImportRec &rRecord, SvxLRSpaceItem &rLR)
1832 sal_uInt32 nXRelTo = SvxMSDffImportRec::RELTO_DEFAULT;
1833 if ( rRecord.pXRelTo )
1835 nXRelTo = *(rRecord.pXRelTo);
1838 // Left adjustments - if horizontally aligned to left of
1839 // margin or column then remove the left wrapping
1840 if (rRecord.nXAlign == 1)
1842 if ((nXRelTo == 0) || (nXRelTo == 2))
1843 rLR.SetLeft((sal_uInt16)0);
1846 // Right adjustments - if horizontally aligned to right of
1847 // margin or column then remove the right wrapping
1848 if (rRecord.nXAlign == 3)
1850 if ((nXRelTo == 0) || (nXRelTo == 2))
1851 rLR.SetRight((sal_uInt16)0);
1854 //Inside margin, remove left wrapping
1855 if ((rRecord.nXAlign == 4) && (nXRelTo == 0))
1857 rLR.SetLeft((sal_uInt16)0);
1860 //Outside margin, remove left wrapping
1861 if ((rRecord.nXAlign == 5) && (nXRelTo == 0))
1863 rLR.SetRight((sal_uInt16)0);
1868 void SwWW8ImplReader::AdjustULWrapForWordMargins(
1869 const SvxMSDffImportRec &rRecord, SvxULSpaceItem &rUL)
1871 sal_uInt32 nYRelTo = SvxMSDffImportRec::RELTO_DEFAULT;
1872 if ( rRecord.pYRelTo )
1874 nYRelTo = *(rRecord.pYRelTo);
1877 // Top adjustment - remove upper wrapping if aligned to page
1878 // printable area or to page
1879 if (rRecord.nYAlign == 1)
1881 if ((nYRelTo == 0) || (nYRelTo == 1))
1882 rUL.SetUpper((sal_uInt16)0);
1885 // Bottom adjustment - remove bottom wrapping if aligned to page or
1886 // printable area or to page
1887 if (rRecord.nYAlign == 3)
1889 if ((nYRelTo == 0) || (nYRelTo == 1))
1890 rUL.SetLower((sal_uInt16)0);
1893 //Remove top margin if aligned vertically inside margin
1894 if ((rRecord.nYAlign == 4) && (nYRelTo == 0))
1895 rUL.SetUpper((sal_uInt16)0);
1898 void SwWW8ImplReader::MapWrapIntoFlyFmt(SvxMSDffImportRec* pRecord,
1899 SwFrmFmt* pFlyFmt)
1901 if (!pRecord || !pFlyFmt)
1902 return;
1904 if (pRecord->nDxWrapDistLeft || pRecord->nDxWrapDistRight)
1906 SvxLRSpaceItem aLR(writer_cast<sal_uInt16>(pRecord->nDxWrapDistLeft),
1907 writer_cast<sal_uInt16>(pRecord->nDxWrapDistRight), 0, 0, RES_LR_SPACE);
1908 AdjustLRWrapForWordMargins(*pRecord, aLR);
1909 pFlyFmt->SetFmtAttr(aLR);
1911 if (pRecord->nDyWrapDistTop || pRecord->nDyWrapDistBottom)
1913 SvxULSpaceItem aUL(writer_cast<sal_uInt16>(pRecord->nDyWrapDistTop),
1914 writer_cast<sal_uInt16>(pRecord->nDyWrapDistBottom), RES_UL_SPACE);
1915 AdjustULWrapForWordMargins(*pRecord, aUL);
1916 pFlyFmt->SetFmtAttr(aUL);
1919 //If we are contoured and have a custom polygon...
1920 if (pRecord->pWrapPolygon && pFlyFmt->GetSurround().IsContour())
1922 if (SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(*pFlyFmt))
1926 Gather round children and hear of a tale that will raise the
1927 hairs on the back of your neck this dark halloween night.
1929 There is a polygon in word that describes the wraping around
1930 the graphic.
1932 Here are some sample values for the simplest case of a square
1933 around some solid coloured graphics
1935 X Y Pixel size of graphic
1936 TopLeft -54 21600 400x400
1937 Bottom Right 0 21546
1939 TopLeft -108 21600 200x200
1940 Bottom Right 0 21492
1942 TopLeft -216 21600 100x100
1943 Bottom Right 0 21384
1945 TopLeft -432 21600 50x50
1946 Bottom Right 0 21168
1948 TopLeft -76 21600 283x212
1949 Bottom Right 0 21498
1951 So given that the size of the values remains pretty much the
1952 same despite the size of the graphic, we can tell that the
1953 polygon is measured in units that are independent of the
1954 graphic. But why does the left corner move a different value
1955 to the left each time, and why does the bottom move upwards
1956 each time, when the right and top remain at the same value ?
1958 I have no idea, but clearly once we calculate the values out
1959 we see that the left margin is always a fixed realworld
1960 distance from the true left and the polygon bottom is the same
1961 fixed value from the bottom. i.e. 15twips.
1963 So here we take our word provided polygon, shift it to the
1964 right by 15twips and rescale it widthwise to shrink the width
1965 a little to fit the now moved right margin back to where it
1966 was, and stretch the height a little to make the bottom move
1967 down the missing 15twips then we get a polygon that matches
1968 what I actually see in word
1971 PolyPolygon aPoly(*pRecord->pWrapPolygon);
1972 const Size &rSize = pNd->GetTwipSize();
1974 Move to the left by 15twips, and rescale to
1975 a) shrink right bound back to orig position
1976 b) stretch bottom bound to where I think it should have been
1977 in the first place
1979 Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
1980 aMoveHack *= Fraction(15, 1);
1981 long nMove(aMoveHack);
1982 aPoly.Move(nMove, 0);
1984 Fraction aHackX(ww::nWrap100Percent, ww::nWrap100Percent + nMove);
1985 Fraction aHackY(ww::nWrap100Percent, ww::nWrap100Percent - nMove);
1986 aPoly.Scale(aHackX, aHackY);
1988 //Turn polygon back into units that match the graphic's
1989 const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
1990 Fraction aMapPolyX(rOrigSize.Width(), ww::nWrap100Percent);
1991 Fraction aMapPolyY(rOrigSize.Height(), ww::nWrap100Percent);
1992 aPoly.Scale(aMapPolyX, aMapPolyY);
1994 // #i47277# - contour is already in unit of the
1995 // graphic prefered unit. Thus, call method <SetContour(..)>
1996 pNd->SetContour(&aPoly);
2001 void
2002 SwWW8ImplReader::SetAttributesAtGrfNode(SvxMSDffImportRec const*const pRecord,
2003 SwFrmFmt *pFlyFmt, WW8_FSPA *pF )
2005 const SwNodeIndex* pIdx = pFlyFmt->GetCntnt(false).GetCntntIdx();
2006 SwGrfNode* pGrfNd;
2007 if( pIdx && 0 != (pGrfNd = rDoc.GetNodes()[pIdx->GetIndex() + 1]->GetGrfNode() ))
2009 Size aSz(pGrfNd->GetTwipSize());
2010 // use type <sal_uInt64> instead of sal_uLong to get correct results
2011 // in the following calculations.
2012 sal_uInt64 rHeight = aSz.Height();
2013 sal_uInt64 rWidth = aSz.Width();
2014 if( !rWidth && pF)
2015 rWidth = pF->nXaRight - pF->nXaLeft;
2016 else if( !rHeight && pF)
2017 rHeight = pF->nYaBottom - pF->nYaTop;
2019 if( pRecord->nCropFromTop || pRecord->nCropFromBottom ||
2020 pRecord->nCropFromLeft || pRecord->nCropFromRight )
2022 SwCropGrf aCrop; // Cropping is stored in 'fixed floats'
2023 // 16.16 (it est fraction times total
2024 if( pRecord->nCropFromTop ) // image width or height resp.)
2025 aCrop.SetTop( static_cast< sal_Int32 >(
2026 ( ( (pRecord->nCropFromTop >> 16 ) * rHeight )
2027 + (((pRecord->nCropFromTop & 0xffff) * rHeight ) >> 16) )));
2028 if( pRecord->nCropFromBottom )
2029 aCrop.SetBottom( static_cast< sal_Int32 >(
2030 ( ( (pRecord->nCropFromBottom >> 16 ) * rHeight )
2031 + (((pRecord->nCropFromBottom & 0xffff) * rHeight ) >> 16) )));
2032 if( pRecord->nCropFromLeft )
2033 aCrop.SetLeft( static_cast< sal_Int32 >(
2034 ( ( (pRecord->nCropFromLeft >> 16 ) * rWidth )
2035 + (((pRecord->nCropFromLeft & 0xffff) * rWidth ) >> 16) )));
2036 if( pRecord->nCropFromRight )
2037 aCrop.SetRight( static_cast< sal_Int32 >(
2038 ( ( (pRecord->nCropFromRight >> 16 ) * rWidth )
2039 + (((pRecord->nCropFromRight & 0xffff) * rWidth ) >> 16) )));
2041 pGrfNd->SetAttr( aCrop );
2044 if (pRecord && pRecord->pObj)
2046 const SfxItemSet& rOldSet = pRecord->pObj->GetMergedItemSet();
2047 //contrast
2048 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFCONTRAST,
2049 SdrGrafContrastItem))
2051 SwContrastGrf aContrast(
2052 WW8ITEMVALUE(rOldSet,
2053 SDRATTR_GRAFCONTRAST, SdrGrafContrastItem));
2054 pGrfNd->SetAttr( aContrast );
2057 //luminance
2058 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFLUMINANCE,
2059 SdrGrafLuminanceItem))
2061 SwLuminanceGrf aLuminance(WW8ITEMVALUE(rOldSet,
2062 SDRATTR_GRAFLUMINANCE, SdrGrafLuminanceItem));
2063 pGrfNd->SetAttr( aLuminance );
2065 //gamma
2066 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA, SdrGrafGamma100Item))
2068 double fVal = WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA,
2069 SdrGrafGamma100Item);
2070 pGrfNd->SetAttr(SwGammaGrf(fVal/100.));
2073 //drawmode
2074 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFMODE, SdrGrafModeItem))
2076 SwDrawModeGrf aDrawMode( static_cast< sal_uInt16 >(WW8ITEMVALUE(rOldSet,
2077 SDRATTR_GRAFMODE, SdrGrafModeItem)) );
2078 pGrfNd->SetAttr( aDrawMode );
2084 SdrObject* SwWW8ImplReader::CreateContactObject(SwFrmFmt* pFlyFmt)
2086 if (pFlyFmt)
2088 SdrObject* pNewObject = mbNewDoc ? 0 : pFlyFmt->FindRealSdrObject();
2089 if (!pNewObject)
2090 pNewObject = pFlyFmt->FindSdrObject();
2091 if (!pNewObject && pFlyFmt->ISA(SwFlyFrmFmt))
2093 SwFlyDrawContact* pContactObject
2094 = new SwFlyDrawContact(static_cast<SwFlyFrmFmt*>(pFlyFmt),
2095 pDrawModel);
2096 pNewObject = pContactObject->GetMaster();
2098 return pNewObject;
2100 return 0;
2103 // Miserable miserable hack to fudge word's graphic layout in RTL mode to ours.
2104 bool SwWW8ImplReader::MiserableRTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
2105 sal_Int16 eHoriOri, sal_Int16 eHoriRel)
2107 if (!IsRightToLeft())
2108 return false;
2109 return RTLGraphicsHack(rLeft, nWidth, eHoriOri, eHoriRel,
2110 maSectionManager.GetPageLeft(),
2111 maSectionManager.GetPageRight(),
2112 maSectionManager.GetPageWidth());
2115 RndStdIds SwWW8ImplReader::ProcessEscherAlign(SvxMSDffImportRec* pRecord,
2116 WW8_FSPA *pFSPA, SfxItemSet &rFlySet, bool /*bOrgObjectWasReplace*/)
2118 OSL_ENSURE(pRecord || pFSPA, "give me something! to work with for anchoring");
2119 if (!pRecord && !pFSPA)
2120 return FLY_AT_PAGE;
2121 sal_Bool bCurSectionVertical = maSectionManager.CurrentSectionIsVertical();
2123 SvxMSDffImportRec aRecordFromFSPA;
2124 if (!pRecord)
2125 pRecord = &aRecordFromFSPA;
2126 if (!(pRecord->pXRelTo) && pFSPA)
2128 pRecord->pXRelTo = new sal_uInt32;
2129 *(pRecord->pXRelTo) = pFSPA->nbx;
2131 if (!(pRecord->pYRelTo) && pFSPA)
2133 pRecord->pYRelTo = new sal_uInt32;
2134 *(pRecord->pYRelTo) = pFSPA->nby;
2137 // nXAlign - abs. Position, Left, Centered, Right, Inside, Outside
2138 // nYAlign - abs. Position, Top, Centered, Bottom, Inside, Outside
2140 // nXRelTo - Page printable area, Page, Column, Character
2141 // nYRelTo - Page printable area, Page, Paragraph, Line
2143 const sal_uInt32 nCntXAlign = 6;
2144 const sal_uInt32 nCntYAlign = 6;
2146 const sal_uInt32 nCntRelTo = 4;
2148 sal_uInt32 nXAlign = nCntXAlign > pRecord->nXAlign ? pRecord->nXAlign : 1;
2149 sal_uInt32 nYAlign = nCntYAlign > pRecord->nYAlign ? pRecord->nYAlign : 1;
2151 if (pFSPA)
2154 #i15718# #i19008#
2155 Strangely in this case the FSPA value seems to be considered before
2156 the newer escher nXRelTo record.
2158 // #i52565# - correct condition checking:
2159 // first check, if <nXRelTo> and <nYRelTo> have default values. This
2160 // is a hint that these values aren't set by the escher import - see
2161 // method <SwMSDffManager::ProcessObj(..)>. Then, check if for each
2162 // values, if it differs from the one in the FSPA.
2164 if ( *(pRecord->pXRelTo) == 2 && *(pRecord->pYRelTo) == 2 && !bCurSectionVertical)
2166 // if <nYRelTo> differs from <FSPA.nby> overwrite <nYRelTo>
2167 if ( pFSPA->nby != *(pRecord->pYRelTo) )
2169 *(pRecord->pYRelTo) = pFSPA->nby;
2174 sal_uInt32 nXRelTo = nCntRelTo > *(pRecord->pXRelTo) ? *(pRecord->pXRelTo) : 1;
2175 sal_uInt32 nYRelTo = nCntRelTo > *(pRecord->pYRelTo) ? *(pRecord->pYRelTo) : 1;
2177 RndStdIds eAnchor = IsInlineEscherHack() ? FLY_AS_CHAR : FLY_AT_CHAR; // #i43718#
2179 SwFmtAnchor aAnchor( eAnchor );
2180 aAnchor.SetAnchor( pPaM->GetPoint() );
2181 rFlySet.Put( aAnchor );
2183 if (pFSPA)
2185 // #i18732#
2186 //Given new layout where everything is changed to be anchored to
2187 //character the following 4 tables may need to be changed.
2189 // horizontal Adjustment
2190 static const sal_Int16 aHoriOriTab[ nCntXAlign ] =
2192 text::HoriOrientation::NONE, // From left position
2193 text::HoriOrientation::LEFT, // left
2194 text::HoriOrientation::CENTER, // centered
2195 text::HoriOrientation::RIGHT, // right
2196 // #i36649#
2197 // - inside -> text::HoriOrientation::LEFT and outside -> text::HoriOrientation::RIGHT
2198 text::HoriOrientation::LEFT, // inside
2199 text::HoriOrientation::RIGHT // outside
2203 // generic vertical Adjustment
2204 static const sal_Int16 aVertOriTab[ nCntYAlign ] =
2206 text::VertOrientation::NONE, // From Top position
2207 text::VertOrientation::TOP, // top
2208 text::VertOrientation::CENTER, // centered
2209 text::VertOrientation::BOTTOM, // bottom
2210 text::VertOrientation::LINE_TOP, // inside (obscure)
2211 text::VertOrientation::LINE_BOTTOM // outside (obscure)
2214 // #i22673# - to-line vertical alignment
2215 static const sal_Int16 aToLineVertOriTab[ nCntYAlign ] =
2217 text::VertOrientation::NONE, // below
2218 text::VertOrientation::LINE_BOTTOM, // top
2219 text::VertOrientation::LINE_CENTER, // centered
2220 text::VertOrientation::LINE_TOP, // bottom
2221 text::VertOrientation::LINE_BOTTOM, // inside (obscure)
2222 text::VertOrientation::LINE_TOP // outside (obscure)
2225 // Adjustment is horizontally relative to...
2226 static const sal_Int16 aHoriRelOriTab[nCntRelTo] =
2228 text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
2229 text::RelOrientation::PAGE_FRAME, // 1 is page margin
2230 text::RelOrientation::FRAME, // 2 is relative to column
2231 text::RelOrientation::CHAR // 3 is relative to character
2234 // Adjustment is vertically relative to...
2235 // #i22673# - adjustment for new vertical alignment at top of line.
2236 static const sal_Int16 aVertRelOriTab[nCntRelTo] =
2238 text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
2239 text::RelOrientation::PAGE_FRAME, // 1 is page margin
2240 text::RelOrientation::FRAME, // 2 is relative to paragraph
2241 text::RelOrientation::TEXT_LINE // 3 is relative to line
2244 sal_Int16 eHoriOri = aHoriOriTab[ nXAlign ];
2245 sal_Int16 eHoriRel = aHoriRelOriTab[ nXRelTo ];
2247 // #i36649# - adjustments for certain alignments
2248 if ( eHoriOri == text::HoriOrientation::LEFT && eHoriRel == text::RelOrientation::PAGE_FRAME )
2250 // convert 'left to page' to 'from left -<width> to page text area'
2251 eHoriOri = text::HoriOrientation::NONE;
2252 eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
2253 const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
2254 pFSPA->nXaLeft = -nWidth;
2255 pFSPA->nXaRight = 0;
2257 else if ( eHoriOri == text::HoriOrientation::RIGHT && eHoriRel == text::RelOrientation::PAGE_FRAME )
2259 // convert 'right to page' to 'from left 0 to right page border'
2260 eHoriOri = text::HoriOrientation::NONE;
2261 eHoriRel = text::RelOrientation::PAGE_RIGHT;
2262 const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
2263 pFSPA->nXaLeft = 0;
2264 pFSPA->nXaRight = nWidth;
2267 // #i24255# - position of floating screen objects in
2268 // R2L layout are given in L2R layout, thus convert them of all
2269 // floating screen objects, which are imported.
2271 // Miserable miserable hack.
2272 SwTwips nWidth = (pFSPA->nXaRight - pFSPA->nXaLeft);
2273 SwTwips nLeft = pFSPA->nXaLeft;
2274 if (MiserableRTLGraphicsHack(nLeft, nWidth, eHoriOri,
2275 eHoriRel))
2277 pFSPA->nXaLeft = nLeft;
2278 pFSPA->nXaRight = pFSPA->nXaLeft + nWidth;
2282 // if the object is anchored inside a table cell, is horizontal aligned
2283 // at frame|character and has wrap through, but its attribute
2284 // 'layout in table cell' isn't set, convert its horizontal alignment to page text area.
2285 // #i84783# - use new method <IsObjectLayoutInTableCell()>
2286 if ( nInTable &&
2287 ( eHoriRel == text::RelOrientation::FRAME || eHoriRel == text::RelOrientation::CHAR ) &&
2288 pFSPA->nwr == 3 &&
2289 !IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell ) )
2291 eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
2295 //Writer honours this wrap distance when aligned as "left" or "right",
2296 //Word doesn't. Writer doesn't honour it when its "from left".
2297 if (eHoriOri == text::HoriOrientation::LEFT)
2298 pRecord->nDxWrapDistLeft=0;
2299 else if (eHoriOri == text::HoriOrientation::RIGHT)
2300 pRecord->nDxWrapDistRight=0;
2302 sal_Int16 eVertRel;
2304 eVertRel = aVertRelOriTab[ nYRelTo ]; // #i18732#
2305 if ( bCurSectionVertical && nYRelTo == 2 )
2306 eVertRel = text::RelOrientation::PAGE_PRINT_AREA;
2307 // #i22673# - fill <eVertOri> in dependence of <eVertRel>
2308 sal_Int16 eVertOri;
2309 if ( eVertRel == text::RelOrientation::TEXT_LINE )
2311 eVertOri = aToLineVertOriTab[ nYAlign ];
2313 else
2315 eVertOri = aVertOriTab[ nYAlign ];
2318 //Below line in word is a positive value, while in writer its
2319 //negative
2320 long nYPos = pFSPA->nYaTop;
2321 // #i22673#
2322 if ((eVertRel == text::RelOrientation::TEXT_LINE) && (eVertOri == text::VertOrientation::NONE))
2323 nYPos = -nYPos;
2325 SwFmtHoriOrient aHoriOri(MakeSafePositioningValue( bCurSectionVertical ? nYPos : pFSPA->nXaLeft ),
2326 bCurSectionVertical ? eVertOri : eHoriOri,
2327 bCurSectionVertical ? eVertRel : eHoriRel);
2328 if( 4 <= nXAlign )
2329 aHoriOri.SetPosToggle(true);
2330 rFlySet.Put( aHoriOri );
2332 rFlySet.Put(SwFmtVertOrient(MakeSafePositioningValue( !bCurSectionVertical ? nYPos : -pFSPA->nXaRight ),
2333 !bCurSectionVertical ? eVertOri : eHoriOri,
2334 !bCurSectionVertical ? eVertRel : eHoriRel ));
2337 return eAnchor;
2340 // #i84783#
2341 bool SwWW8ImplReader::IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTableCell ) const
2343 bool bIsObjectLayoutInTableCell = false;
2345 if ( bVer8 )
2347 const sal_uInt16 nWWVersion = pWwFib->nProduct & 0xE000;
2348 switch ( nWWVersion )
2350 case 0x0000: // version 8 aka Microsoft Word 97
2352 bIsObjectLayoutInTableCell = false;
2353 OSL_ENSURE( nLayoutInTableCell == 0xFFFFFFFF,
2354 "no explicit object attribute layout in table cell expected." );
2356 break;
2357 case 0x2000: // version 9 aka Microsoft Word 2000
2358 case 0x4000: // version 10 aka Microsoft Word 2002
2359 case 0x6000: // version 11 aka Microsoft Word 2003
2360 case 0x8000: // version 12 aka Microsoft Word 2007
2361 case 0xC000: // version 14 aka Microsoft Word 2010
2363 // #i98037#
2364 // adjustment of conditions needed after deeper analysis of
2365 // certain test cases.
2366 if ( nLayoutInTableCell == 0xFFFFFFFF || // no explicit attribute value given
2367 nLayoutInTableCell == 0x80008000 ||
2368 ( nLayoutInTableCell & 0x02000000 &&
2369 !(nLayoutInTableCell & 0x80000000 ) ) )
2371 bIsObjectLayoutInTableCell = true;
2373 else
2375 bIsObjectLayoutInTableCell = false;
2378 break;
2379 default:
2381 OSL_FAIL( "unknown version." );
2386 return bIsObjectLayoutInTableCell;
2389 SwFrmFmt* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp )
2391 if( nIniFlags & WW8FL_NO_GRAFLAYER )
2392 return 0;
2394 ::SetProgressState(nProgress, mpDocShell); // Update
2396 nDrawCpO = pWwFib->GetBaseCp(pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX);
2398 GrafikCtor();
2400 WW8PLCFspecial* pPF = pPlcxMan->GetFdoa();
2401 if( !pPF )
2403 OSL_ENSURE( !this, "Where is the grapic (1) ?" );
2404 return 0;
2407 if( bVer67 )
2409 long nOldPos = pStrm->Tell();
2411 nDrawXOfs = nDrawYOfs = 0;
2412 ReadGrafLayer1( pPF, nGrafAnchorCp );
2414 pStrm->Seek( nOldPos );
2415 return 0;
2418 //Normal case of Word 8+ version stuff
2419 pPF->SeekPos( nGrafAnchorCp );
2421 WW8_FC nStartFc;
2422 void* pF0;
2423 if( !pPF->Get( nStartFc, pF0 ) ){
2424 OSL_ENSURE( !this, "+Wo ist die Grafik (2) ?" );
2425 return 0;
2428 WW8_FSPA_SHADOW* pFS = (WW8_FSPA_SHADOW*)pF0;
2429 WW8_FSPA* pF;
2430 #ifdef __WW8_NEEDS_COPY
2431 WW8_FSPA aFSFA;
2432 pF = &aFSFA;
2433 WW8FSPAShadowToReal( pFS, pF );
2434 #else
2435 pF = (WW8_FSPA*)pFS;
2436 #endif // defined __WW8_NEEDS_COPY
2437 if( !pF->nSpId )
2439 OSL_ENSURE( !this, "+Wo ist die Grafik (3) ?" );
2440 return 0;
2443 if (!pMSDffManager->GetModel())
2444 pMSDffManager->SetModel(pDrawModel, 1440);
2447 Rectangle aRect(pF->nXaLeft, pF->nYaTop, pF->nXaRight, pF->nYaBottom);
2448 SvxMSDffImportData aData( aRect );
2451 #i20540#
2452 The SdrOle2Obj will try and manage any ole objects it finds, causing all
2453 sorts of trouble later on
2455 SwDocShell* pPersist = rDoc.GetDocShell();
2456 rDoc.SetDocShell(0); //#i20540# Persist guard
2458 SdrObject* pObject = 0;
2459 bool bOk = (pMSDffManager->GetShape(pF->nSpId, pObject, aData) && pObject);
2461 rDoc.SetDocShell(pPersist); //#i20540# Persist guard
2463 if (!bOk)
2465 OSL_ENSURE( !this, "Where is the Shape ?" );
2466 return 0;
2469 bool bDone = false;
2470 SdrObject* pOurNewObject = 0;
2471 bool bReplaceable = false;
2473 switch (SdrObjKind(pObject->GetObjIdentifier()))
2475 case OBJ_GRAF:
2476 bReplaceable = true;
2477 bDone = true;
2478 break;
2479 case OBJ_OLE2:
2480 bReplaceable = true;
2481 break;
2482 default:
2483 break;
2487 // when in a header or footer word appears to treat all elements as wrap through
2489 // Umfluss-Modus ermitteln
2490 SfxItemSet aFlySet(rDoc.GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1);
2491 SwSurround eSurround = SURROUND_PARALLEL;
2492 bool bContour = false;
2493 switch (pF->nwr)
2495 case 0: //0 like 2, but doesn't require absolute object
2496 case 2: //2 wrap around absolute object
2497 eSurround = SURROUND_PARALLEL;
2498 break;
2499 case 1: //1 no text next to shape
2500 eSurround = SURROUND_NONE;
2501 break;
2502 case 3: //3 wrap as if no object present
2503 eSurround = SURROUND_THROUGHT;
2504 break;
2505 case 4: //4 wrap tightly around object
2506 case 5: //5 wrap tightly, but allow holes
2507 eSurround = SURROUND_PARALLEL;
2508 bContour = true;
2509 break;
2512 // bei Modus 2 oder 4 auch den Zusatzparameter beruecksichtigen
2513 if ( (2 == pF->nwr) || (4 == pF->nwr) )
2515 switch( pF->nwrk )
2517 //0 wrap both sides
2518 case 0:
2519 eSurround = SURROUND_PARALLEL;
2520 break;
2521 //1 wrap only on left
2522 case 1:
2523 eSurround = SURROUND_LEFT;
2524 break;
2525 //2 wrap only on right
2526 case 2:
2527 eSurround = SURROUND_RIGHT;
2528 break;
2529 //3 wrap only on largest side
2530 case 3:
2531 eSurround = SURROUND_IDEAL;
2532 break;
2536 SwFmtSurround aSur( eSurround );
2537 aSur.SetContour( bContour );
2538 aSur.SetOutside(true); // Winword kann nur Aussen-Konturen
2539 aFlySet.Put( aSur );
2541 // eingelesenes Objekt (kann eine ganze Gruppe sein) jetzt korrekt
2542 // positionieren usw.
2544 OSL_ENSURE(!((aData.size() != 1) && bReplaceable),
2545 "Replaceable drawing with > 1 entries ?");
2547 if (aData.size() != 1)
2548 bReplaceable = false;
2550 SvxMSDffImportRec* pRecord = 0;
2552 Get the record for top level object, so we can get the word anchoring
2553 and wrapping information for it.
2555 for (MSDffImportRecords::const_iterator it = aData.begin();
2556 it != aData.end(); ++it) // MSVC2008 wants const_iterator here???
2558 if (it->pObj == pObject)
2560 pRecord = &const_cast<SvxMSDffImportRec&>(*it);
2561 break;
2565 OSL_ENSURE(pRecord, "how did that happen?");
2566 if (!pRecord)
2567 return 0;
2569 const bool bLayoutInTableCell =
2570 nInTable && IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell );
2572 // #i18732# - Switch on 'follow text flow', if object is laid out
2573 // inside table cell and its wrapping isn't 'SURROUND_THROUGH'
2574 if (bLayoutInTableCell && eSurround != SURROUND_THROUGHT)
2576 SwFmtFollowTextFlow aFollowTextFlow( sal_True );
2577 aFlySet.Put( aFollowTextFlow );
2581 //#i21847#
2582 //Some shapes are set to *hidden*, don't import those ones.
2583 if (pRecord->bHidden)
2584 return 0;
2586 // If we are to be "below text" then we are not to be opaque
2587 // #i14045# MM If we are in a header or footer then make the object transparent
2588 // Not exactly like word but close enough for now
2590 // both flags <bBelowText> and <bDrawHell> have to be set to move object into the background.
2591 // #i46794# - it reveals that value of flag <bBelowText> can be neglected.
2592 const bool bMoveToBackgrd = pRecord->bDrawHell ||
2593 ( ( bIsHeader || bIsFooter ) && pF->nwr == 3 );
2594 if ( bMoveToBackgrd )
2595 aFlySet.Put(SvxOpaqueItem(RES_OPAQUE,false));
2597 String aObjName = pObject->GetName();
2599 SwFrmFmt* pRetFrmFmt = 0;
2600 if (bReplaceable)
2602 //Single graphics or ole objects
2603 pRetFrmFmt = ImportReplaceableDrawables(pObject, pOurNewObject, pRecord,
2604 pF, aFlySet);
2606 else
2608 //Drawing objects, (e.g. ovals or drawing groups)
2609 if (pF->bRcaSimple)
2611 pF->nbx = WW8_FSPA::RelPageBorder;
2612 pF->nby = WW8_FSPA::RelPageBorder;
2615 RndStdIds eAnchor = ProcessEscherAlign(pRecord, pF, aFlySet,
2616 bReplaceable);
2618 // Should we, and is it possible to make this into a writer textbox
2619 if ((!(nIniFlags1 & WW8FL_NO_FLY_FOR_TXBX)) && pRecord->bReplaceByFly)
2621 pRetFrmFmt = ConvertDrawTextToFly(pObject, pOurNewObject, pRecord,
2622 eAnchor, pF, aFlySet);
2623 if (pRetFrmFmt)
2624 bDone = true;
2627 if (!bDone)
2629 sw::util::SetLayer aSetLayer(rDoc);
2630 if ( bMoveToBackgrd )
2631 aSetLayer.SendObjectToHell(*pObject);
2632 else
2633 aSetLayer.SendObjectToHeaven(*pObject);
2635 if (!IsInlineEscherHack())
2637 /* Need to make sure that the correct layer ordering is applied. */
2638 // pass information, if object is in page header|footer to method.
2639 pWWZOrder->InsertEscherObject( pObject, pF->nSpId,
2640 bIsHeader || bIsFooter );
2642 else
2644 pWWZOrder->InsertTextLayerObject(pObject);
2647 pRetFrmFmt = rDoc.Insert(*pPaM, *pObject, &aFlySet, NULL);
2649 OSL_ENSURE(pRetFrmFmt->GetAnchor().GetAnchorId() ==
2650 eAnchor, "Not the anchor type requested!");
2653 Insert text if necessary into textboxes contained in groups.
2655 if (!aData.empty())
2657 for (MSDffImportRecords::const_iterator it = aData.begin();
2658 it != aData.end(); ++it)
2660 pRecord = &const_cast<SvxMSDffImportRec&>(*it);
2661 if (pRecord->pObj && pRecord->aTextId.nTxBxS)
2662 { // #i52825# pRetFrmFmt can be NULL
2663 pRetFrmFmt = MungeTextIntoDrawBox(pRecord->pObj,
2664 pRecord, nGrafAnchorCp, pRetFrmFmt);
2671 // #i44344#, #i44681# - positioning attributes already set
2672 if ( pRetFrmFmt /*#i52825# */ && pRetFrmFmt->ISA(SwDrawFrmFmt) )
2674 static_cast<SwDrawFrmFmt*>(pRetFrmFmt)->PosAttrSet();
2676 if (!IsInlineEscherHack())
2677 MapWrapIntoFlyFmt(pRecord, pRetFrmFmt);
2679 // Set frame name with object name
2680 if( pRetFrmFmt /*#i52825# */ && aObjName.Len() )
2681 pRetFrmFmt->SetName( aObjName );
2682 return AddAutoAnchor(pRetFrmFmt);
2685 SwFrmFmt *SwWW8ImplReader::AddAutoAnchor(SwFrmFmt *pFmt)
2688 * anchored to character at the current position will move along the
2689 * paragraph as text is added because we are at the insertion point.
2691 * Leave to later and set the correct location then.
2693 if ((pFmt) && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR))
2695 pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFmt);
2697 return pFmt;
2700 SwFrmFmt* SwWW8ImplReader::MungeTextIntoDrawBox(SdrObject* pTrueObject,
2701 SvxMSDffImportRec *pRecord, long nGrafAnchorCp, SwFrmFmt* pRetFrmFmt)
2703 SdrTextObj* pSdrTextObj;
2705 // Pruefen, ob Gruppenobjekt (z.B. zwei Klammern) vorliegt
2706 if (SdrObjGroup* pThisGroup = PTR_CAST(SdrObjGroup, pRecord->pObj))
2708 // Gruppenobjekte haben keinen Text. Fuege ein Textobjekt in die
2709 // Gruppe ein, um den Text zu halten.
2710 pSdrTextObj = new SdrRectObj( OBJ_TEXT, pThisGroup->GetCurrentBoundRect());
2712 SfxItemSet aSet(pDrawModel->GetItemPool());
2713 aSet.Put(XFillStyleItem(XFILL_NONE));
2714 aSet.Put(XLineStyleItem(XLINE_NONE));
2715 aSet.Put(SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE ));
2716 aSet.Put(SdrTextAutoGrowHeightItem(false));
2717 aSet.Put(SdrTextAutoGrowWidthItem(false));
2718 pSdrTextObj->SetMergedItemSet(aSet);
2720 long nAngle = pRecord->nTextRotationAngle;
2721 if ( nAngle )
2723 double a = nAngle*nPi180;
2724 pSdrTextObj->NbcRotate(pSdrTextObj->GetCurrentBoundRect().Center(), nAngle,
2725 sin(a), cos(a) );
2728 pSdrTextObj->NbcSetLayer( pThisGroup->GetLayer() );
2729 pThisGroup->GetSubList()->NbcInsertObject(pSdrTextObj);
2731 else
2732 pSdrTextObj = PTR_CAST(SdrTextObj, pRecord->pObj);
2734 if( pSdrTextObj )
2736 Size aObjSize(pSdrTextObj->GetSnapRect().GetWidth(),
2737 pSdrTextObj->GetSnapRect().GetHeight());
2739 // Objekt ist Bestandteil einer Gruppe?
2740 SdrObject* pGroupObject = pSdrTextObj->GetUpGroup();
2742 sal_uInt32 nOrdNum = pSdrTextObj->GetOrdNum();
2743 bool bEraseThisObject;
2744 InsertTxbxText( pSdrTextObj, &aObjSize, pRecord->aTextId.nTxBxS,
2745 pRecord->aTextId.nSequence, nGrafAnchorCp, pRetFrmFmt,
2746 (pSdrTextObj != pTrueObject) || (0 != pGroupObject),
2747 bEraseThisObject, 0, 0, 0, 0, pRecord);
2749 // wurde dieses Objekt ersetzt ??
2750 if (bEraseThisObject)
2752 if( pGroupObject || (pSdrTextObj != pTrueObject) )
2754 // Objekt wurde bereits (in der Gruppe und) der Drawing-Page
2755 // durch ein neues SdrGrafObj ersetzt.
2757 SdrObject* pNewObj = pGroupObject ?
2758 pGroupObject->GetSubList()->GetObj(nOrdNum) : pTrueObject;
2759 if (pSdrTextObj != pNewObj)
2761 // Objekt in der Z-Order-Liste ersetzen
2762 pMSDffManager->ExchangeInShapeOrder(pSdrTextObj, 0,0, pNewObj);
2763 // Objekt jetzt noch loeschen
2764 SdrObject::Free( pRecord->pObj );
2765 // und das neue Objekt merken.
2766 pRecord->pObj = pNewObj;
2769 else
2771 // Objekt aus der Z-Order-Liste loeschen
2772 pMSDffManager->RemoveFromShapeOrder( pSdrTextObj );
2773 // Objekt aus der Drawing-Page rausnehmen
2774 if( pSdrTextObj->GetPage() )
2775 pDrawPg->RemoveObject( pSdrTextObj->GetOrdNum() );
2776 // und FrameFormat entfernen, da durch Grafik ersetzt (dies
2777 // loescht auch das Objekt)
2778 rDoc.DelFrmFmt( pRetFrmFmt );
2779 pRetFrmFmt = 0;
2780 // auch den Objektmerker loeschen
2781 pRecord->pObj = 0;
2784 else
2786 // ww8-default Randabstand einsetzen
2787 SfxItemSet aItemSet(pDrawModel->GetItemPool(),
2788 SDRATTR_TEXT_LEFTDIST, SDRATTR_TEXT_LOWERDIST);
2789 aItemSet.Put( SdrTextLeftDistItem( pRecord->nDxTextLeft ) );
2790 aItemSet.Put( SdrTextRightDistItem( pRecord->nDxTextRight ) );
2791 aItemSet.Put( SdrTextUpperDistItem( pRecord->nDyTextTop ) );
2792 aItemSet.Put( SdrTextLowerDistItem( pRecord->nDyTextBottom ) );
2793 pSdrTextObj->SetMergedItemSetAndBroadcast(aItemSet);
2796 return pRetFrmFmt;
2799 SwFlyFrmFmt* SwWW8ImplReader::ConvertDrawTextToFly(SdrObject* &rpObject,
2800 SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, RndStdIds eAnchor,
2801 WW8_FSPA *pF, SfxItemSet &rFlySet)
2803 SwFlyFrmFmt* pRetFrmFmt = 0;
2804 long nStartCp;
2805 long nEndCp;
2807 // Check if this textbox chain contains text as conversion of an empty
2808 // chain would not make sense.
2809 if ( TxbxChainContainsRealText(pRecord->aTextId.nTxBxS,nStartCp,nEndCp) )
2811 // The Text is not read into SdrTextObj! Rather insert a frame and
2812 // insert the text from nStartCp to nEndCp.
2814 // More attributes can be used in a frame compared to the
2815 // Edit-Enging, and it can contain field, OLEs or graphics...
2816 Rectangle aInnerDist(pRecord->nDxTextLeft, pRecord->nDyTextTop,
2817 pRecord->nDxTextRight, pRecord->nDyTextBottom);
2819 SwFmtFrmSize aFrmSize(ATT_FIX_SIZE, pF->nXaRight - pF->nXaLeft, pF->nYaBottom - pF->nYaTop);
2820 aFrmSize.SetWidthSizeType(pRecord->bAutoWidth ? ATT_VAR_SIZE : ATT_FIX_SIZE);
2821 rFlySet.Put(aFrmSize);
2823 MatchSdrItemsIntoFlySet( rpObject, rFlySet, pRecord->eLineStyle,
2824 pRecord->eLineDashing, pRecord->eShapeType, aInnerDist );
2827 SdrTextObj *pSdrTextObj = PTR_CAST(SdrTextObj, rpObject);
2828 if (pSdrTextObj && pSdrTextObj->IsVerticalWriting())
2829 rFlySet.Put(SvxFrameDirectionItem(FRMDIR_VERT_TOP_RIGHT, RES_FRAMEDIR));
2831 pRetFrmFmt = rDoc.MakeFlySection(eAnchor, pPaM->GetPoint(), &rFlySet);
2832 OSL_ENSURE(pRetFrmFmt->GetAnchor().GetAnchorId() == eAnchor,
2833 "Not the anchor type requested!");
2835 // if everything is OK, find pointer on new object and correct
2836 // Z-order list (oder delete entry)
2837 rpOurNewObject = CreateContactObject(pRetFrmFmt);
2839 // remove old object from the Z-Order list
2840 pMSDffManager->RemoveFromShapeOrder( rpObject );
2842 // and delete the object
2843 SdrObject::Free( rpObject );
2845 NB: only query pOrgShapeObject starting here!
2848 if (rpOurNewObject)
2851 We do not store our rpOutNewObject in the ShapeOrder because we
2852 have a FrmFmt from which we can regenerate the contact object when
2853 we need it. Because, we can have frames anchored to paragraphs in
2854 header/footers and we can copy header/footers, if we do copy a
2855 header/footer with a nonpage anchored frame in it then the contact
2856 objects are invalidated. Under this condition the FrmFmt will be
2857 updated to reflect this change and can be used to get a new
2858 contact object, while a raw rpOutNewObject stored here becomes
2859 deleted and useless.
2861 pMSDffManager->StoreShapeOrder(pF->nSpId,
2862 (((sal_uLong)pRecord->aTextId.nTxBxS) << 16) +
2863 pRecord->aTextId.nSequence, 0, pRetFrmFmt);
2865 // The Kontakt object has to be inserted into the draw page, so
2866 // SwWW8ImplReader::LoadDoc1() can determine the z-order.
2867 if (!rpOurNewObject->IsInserted())
2869 // pass information, if object is in page header|footer to method.
2870 pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
2871 bIsHeader || bIsFooter );
2875 // Box-0 receives the text for the whole chain!
2876 if( !pRecord->aTextId.nSequence )
2878 // save flags etc and reset them
2879 WW8ReaderSave aSave( this );
2881 MoveInsideFly(pRetFrmFmt);
2883 SwNodeIndex aStart(pPaM->GetPoint()->nNode);
2885 pWWZOrder->InsideEscher(pF->nSpId);
2887 // read in the text
2888 bTxbxFlySection = true;
2889 bool bJoined = ReadText(nStartCp, (nEndCp-nStartCp),
2890 MAN_MAINTEXT == pPlcxMan->GetManType() ?
2891 MAN_TXBX : MAN_TXBX_HDFT);
2893 pWWZOrder->OutsideEscher();
2895 MoveOutsideFly(pRetFrmFmt, aSave.GetStartPos(),!bJoined);
2897 aSave.Restore( this );
2900 return pRetFrmFmt;
2903 void MatchEscherMirrorIntoFlySet(const SvxMSDffImportRec &rRecord,
2904 SfxItemSet &rFlySet)
2906 if (rRecord.bVFlip || rRecord.bHFlip)
2908 MirrorGraph eType(RES_MIRROR_GRAPH_DONT);
2909 if (rRecord.bVFlip && rRecord.bHFlip)
2910 eType = RES_MIRROR_GRAPH_BOTH;
2911 else if (rRecord.bVFlip)
2912 eType = RES_MIRROR_GRAPH_HOR;
2913 else
2914 eType = RES_MIRROR_GRAPH_VERT;
2915 rFlySet.Put( SwMirrorGrf(eType) );
2919 SwFlyFrmFmt* SwWW8ImplReader::ImportReplaceableDrawables( SdrObject* &rpObject,
2920 SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, WW8_FSPA *pF,
2921 SfxItemSet &rFlySet )
2923 SwFlyFrmFmt* pRetFrmFmt = 0;
2924 long nWidthTw = pF->nXaRight - pF->nXaLeft;
2925 if (0 > nWidthTw)
2926 nWidthTw = 0;
2927 long nHeightTw = pF->nYaBottom - pF->nYaTop;
2928 if (0 > nHeightTw)
2929 nHeightTw = 0;
2931 ProcessEscherAlign(pRecord, pF, rFlySet, true);
2933 rFlySet.Put(SwFmtFrmSize(ATT_FIX_SIZE, nWidthTw, nHeightTw));
2935 SfxItemSet aGrSet(rDoc.GetAttrPool(), RES_GRFATR_BEGIN, RES_GRFATR_END-1);
2937 if (pRecord)
2939 //Note that the escher inner distance only seems to be honoured in
2940 //word for textboxes, not for graphics and ole objects.
2941 Rectangle aInnerDist(0, 0, 0, 0);
2943 MatchSdrItemsIntoFlySet(rpObject, rFlySet, pRecord->eLineStyle,
2944 pRecord->eLineDashing, pRecord->eShapeType, aInnerDist);
2946 MatchEscherMirrorIntoFlySet(*pRecord, aGrSet);
2949 String aObjectName(rpObject->GetName());
2950 if (OBJ_OLE2 == SdrObjKind(rpObject->GetObjIdentifier()))
2951 pRetFrmFmt = InsertOle(*((SdrOle2Obj*)rpObject), rFlySet, aGrSet);
2952 else
2954 const SdrGrafObj *pGrf= (const SdrGrafObj*)rpObject;
2955 bool bDone = false;
2956 if (pGrf->IsLinkedGraphic() && !pGrf->GetFileName().isEmpty())
2958 GraphicType eType = pGrf->GetGraphicType();
2959 String aGrfName(
2960 URIHelper::SmartRel2Abs(
2961 INetURLObject(sBaseURL), pGrf->GetFileName(),
2962 URIHelper::GetMaybeFileHdl()));
2963 // correction of fix for issue #i10939#:
2964 // One of the two conditions have to be true to insert the graphic
2965 // as a linked graphic -
2966 if (GRAPHIC_NONE == eType || CanUseRemoteLink(aGrfName))
2968 pRetFrmFmt = rDoc.Insert(*pPaM, aGrfName, aEmptyStr, 0,
2969 &rFlySet, &aGrSet, NULL);
2970 bDone = true;
2973 if (!bDone)
2975 const Graphic& rGraph = pGrf->GetGraphic();
2976 pRetFrmFmt = rDoc.Insert(*pPaM, aEmptyStr, aEmptyStr, &rGraph,
2977 &rFlySet, &aGrSet, NULL);
2981 if (pRetFrmFmt)
2983 if( pRecord )
2985 if( OBJ_OLE2 != SdrObjKind(rpObject->GetObjIdentifier()) )
2986 SetAttributesAtGrfNode( pRecord, pRetFrmFmt, pF );
2988 // mehrfaches Auftreten gleicher Grafik-Namen vermeiden
2989 maGrfNameGenerator.SetUniqueGraphName(pRetFrmFmt, aObjectName);
2991 //falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste
2992 //entsprechend korrigieren (oder Eintrag loeschen)
2993 rpOurNewObject = CreateContactObject(pRetFrmFmt);
2995 // altes Objekt aus der Z-Order-Liste entfernen
2996 pMSDffManager->RemoveFromShapeOrder( rpObject );
2997 // aus der Drawing-Page rausnehmen
2998 if( rpObject->GetPage() )
2999 pDrawPg->RemoveObject( rpObject->GetOrdNum() );
3001 // und das Objekt loeschen
3002 SdrObject::Free( rpObject );
3004 Achtung: ab jetzt nur noch pOrgShapeObject abfragen!
3007 // Kontakt-Objekt in die Z-Order-Liste und die Page aufnehmen
3008 if (rpOurNewObject)
3010 if (!bHdFtFtnEdn)
3011 pMSDffManager->StoreShapeOrder(pF->nSpId, 0, rpOurNewObject, 0 );
3013 // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit in
3014 // SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden kann !!!
3015 if (!rpOurNewObject->IsInserted())
3017 // pass information, if object is in page header|footer to method.
3018 pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
3019 bIsHeader || bIsFooter );
3022 return pRetFrmFmt;
3025 void SwWW8ImplReader::GrafikCtor() // Fuer SVDraw und VCControls und Escher
3027 if (!pDrawModel)
3029 rDoc.GetOrCreateDrawModel(); // #i52858# - method name changed
3030 pDrawModel = rDoc.GetDrawModel();
3031 OSL_ENSURE(pDrawModel, "Kann DrawModel nicht anlegen");
3032 pDrawPg = pDrawModel->GetPage(0);
3034 pMSDffManager = new SwMSDffManager(*this);
3035 pMSDffManager->SetModel(pDrawModel, 1440);
3037 Now the dff manager always needs a controls //converter as well, but a
3038 control converter may still exist //without a dffmanager. cmc
3040 pFormImpl = new SwMSConvertControls(mpDocShell, pPaM);
3042 pWWZOrder = new wwZOrderer(sw::util::SetLayer(rDoc), pDrawPg,
3043 pMSDffManager ? pMSDffManager->GetShapeOrders() : 0);
3047 void SwWW8ImplReader::GrafikDtor()
3049 DELETEZ(mpDrawEditEngine); // evtl. von Grafik angelegt
3050 DELETEZ(pWWZOrder); // dito
3053 void SwWW8FltAnchorStack::AddAnchor(const SwPosition& rPos, SwFrmFmt *pFmt)
3055 OSL_ENSURE(pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR,
3056 "Don't use fltanchors with inline frames, slap!");
3057 NewAttr(rPos, SwFltAnchor(pFmt));
3060 void SwWW8FltAnchorStack::Flush()
3062 size_t nCnt = size();
3063 for (size_t i=0; i < nCnt; ++i)
3065 SwFltStackEntry &rEntry = (*this)[i];
3066 SwPosition aDummy(rEntry.m_aMkPos.m_nNode);
3067 SetAttrInDoc(aDummy, rEntry);
3068 DeleteAndDestroy(i--);
3069 --nCnt;
3073 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */