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