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