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