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