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