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