Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx
Warning:line 1175, column 18
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ww8graf.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/oox/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <comphelper/string.hxx>
21#include <svl/urihelper.hxx>
22#include <hintids.hxx>
23#include <osl/endian.h>
24#include <sal/log.hxx>
25#include <editeng/lrspitem.hxx>
26#include <svx/xfillit0.hxx>
27#include <svx/xlineit0.hxx>
28#include <svx/xlnclit.hxx>
29#include <svx/xlnwtit.hxx>
30#include <svx/xlndsit.hxx>
31#include <svx/xlnstit.hxx>
32#include <svx/xlnedit.hxx>
33#include <svx/xlnstwit.hxx>
34#include <svx/xlnedwit.hxx>
35#include <svx/xlnstcit.hxx>
36#include <svx/xlnedcit.hxx>
37#include <svx/xflclit.hxx>
38#include <svx/xbtmpit.hxx>
39#include <svx/svdmodel.hxx>
40#include <svx/svdocapt.hxx>
41#include <svx/sxctitm.hxx>
42#include <svx/sdggaitm.hxx>
43#include <svx/sdgluitm.hxx>
44#include <svx/sdgmoitm.hxx>
45#include <svx/sdmetitm.hxx>
46#include <svx/sdooitm.hxx>
47#include <svx/sdshitm.hxx>
48#include <svx/sdsxyitm.hxx>
49#include <svx/sdtagitm.hxx>
50#include <svx/sdtditm.hxx>
51#include <svx/sdtfsitm.hxx>
52#include <editeng/editeng.hxx>
53#include <svx/svdpage.hxx>
54#include <svx/svdopath.hxx>
55#include <svx/svdocirc.hxx>
56#include <editeng/outlobj.hxx>
57#include <svx/svdogrp.hxx>
58#include <svx/svdograf.hxx>
59#include <svx/svdoole2.hxx>
60#include <editeng/ulspitem.hxx>
61#include <editeng/brushitem.hxx>
62#include <editeng/opaqitem.hxx>
63#include <editeng/shaditem.hxx>
64#include <editeng/boxitem.hxx>
65#include <editeng/outliner.hxx>
66#include <editeng/frmdiritem.hxx>
67#include <svx/xfltrit.hxx>
68#include <filter/msfilter/msdffimp.hxx>
69#include <grfatr.hxx>
70#include <fmtornt.hxx>
71#include <fmtcntnt.hxx>
72#include <frmfmt.hxx>
73#include <fmtanchr.hxx>
74#include <pam.hxx>
75#include <doc.hxx>
76#include <drawdoc.hxx>
77#include <IDocumentDrawModelAccess.hxx>
78#include <ndgrf.hxx>
79#include <dcontact.hxx>
80#include <docsh.hxx>
81#include <mdiexp.hxx>
82#include "ww8struc.hxx"
83#include "ww8scan.hxx"
84#include "ww8par.hxx"
85#include "ww8par2.hxx"
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 <o3tl/enumrange.hxx>
99#include <o3tl/safeint.hxx>
100#include <memory>
101#include <filter/msfilter/escherex.hxx>
102#include "sprmids.hxx"
103
104using ::editeng::SvxBorderLine;
105using namespace ::com::sun::star;
106using namespace sw::types;
107using namespace sw::util;
108
109// helper methods
110static Color WW8TransCol(SVBT32 nWC)
111{
112#if 1 // 1 = use predefined color, 0 = ignore
113
114 // color table to convert RGB values to pre-defined colors
115 // (to make the writer UI show the right color names)
116 // the table is split in base 3, the greys are missing as
117 // they don't fit into that system (4 values: bw, wb, 2 * grey)
118 static const Color eColA[] = { // B G R B G R B G R
119 COL_BLACK, COL_RED, COL_LIGHTRED, // 0 0 0, 0 0 1, 0 0 2
120 COL_GREEN, COL_BROWN, COL_BLACK, // 0 1 0, 0 1 1, 0 1 2
121 COL_LIGHTGREEN, COL_BLACK, COL_YELLOW, // 0 2 0, 0 2 1, 0 2 2
122 COL_BLUE, COL_MAGENTA, COL_BLACK, // 1 0 0, 1 0 1, 1 0 2
123 COL_CYAN, COL_LIGHTGRAY, COL_BLACK, // 1 1 0, 1 1 1, 1 1 2
124 COL_BLACK, COL_BLACK, COL_BLACK, // 1 2 0, 1 2 1, 1 2 2
125 COL_LIGHTBLUE, COL_BLACK, COL_LIGHTMAGENTA, // 2 0 0, 2 0 1, 2 0 2
126 COL_BLACK, COL_BLACK, COL_BLACK, // 2 1 0, 2 1 1, 2 1 2
127 COL_LIGHTCYAN, COL_BLACK, COL_WHITE }; // 2 2 0, 2 2 1, 2 2 2
128
129 // In nWC[3] is a byte that's not described in the WW documentation.
130 // Its meaning appears to be the following: For 0, it's a normal color
131 // whose RGB values are in nWC[0..2]. If nWC[3] is 0x1, 0x7d or 0x83,
132 // it's a grey value whose black portion is given in 0.5% in nWC[0].
133 // I guess that BIT(0) in nWC[3] is relevant for distinguishing RGB/Grey.
134
135 if( !( nWC[3] & 0x1 ) && // not special (grey)
136 ( ( nWC[0] == 0 || nWC[0]== 0x80 || nWC[0] == 0xff ) // R
137 && ( nWC[1] == 0 || nWC[1]== 0x80 || nWC[1] == 0xff ) // G
138 && ( nWC[2] == 0 || nWC[2]== 0x80 || nWC[2] == 0xff ) ) ){// B
139 int nIdx = 0; // and now: Idx-calculation in base 3
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 eColA[nIdx]; // default color
148 }
149#endif
150
151 if (nWC[3] & 0x1)
152 {
153 // Special color gray
154 sal_uInt8 u = static_cast<sal_uInt8>( static_cast<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
162void wwFrameNamer::SetUniqueGraphName(SwFrameFormat *pFrameFormat, const OUString &rFixed)
163{
164 if (mbIsDisabled || rFixed.isEmpty())
165 return;
166
167 pFrameFormat->SetName(msSeed+OUString::number(++mnImportedGraphicsCount) + ": " + rFixed);
168}
169
170// ReadGrafStart reads object data and if necessary creates an anchor
171bool SwWW8ImplReader::ReadGrafStart(void* pData, short nDataSiz,
172 WW8_DPHEAD const * pHd, SfxAllItemSet &rSet)
173{
174 if (SVBT16ToUInt16(pHd->cb) < sizeof(WW8_DPHEAD) + nDataSiz)
175 {
176 OSL_ENSURE( false, "+graphic element: too short?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "176" ": "), "%s", "+graphic element: too short?"); } } while
(false)
;
177 m_pStrm->SeekRel(SVBT16ToUInt16(pHd->cb) - sizeof(WW8_DPHEAD));
178 return false;
179 }
180
181 bool bCouldRead = checkRead(*m_pStrm, pData, nDataSiz);
182 OSL_ENSURE(bCouldRead, "Short Graphic header")do { if (true && (!(bCouldRead))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "182" ": "), "%s", "Short Graphic header"); } } while (false
)
;
183 if (!bCouldRead)
184 return false;
185
186 SwFormatAnchor aAnchor( RndStdIds::FLY_AT_CHAR );
187 aAnchor.SetAnchor( m_pPaM->GetPoint() );
188 rSet.Put( aAnchor );
189
190 m_nDrawXOfs2 = m_nDrawXOfs;
191 m_nDrawYOfs2 = m_nDrawYOfs;
192
193 return true;
194}
195
196// SetStdAttr() sets standard attributes
197static void SetStdAttr( SfxItemSet& rSet, WW8_DP_LINETYPE& rL,
198 WW8_DP_SHADOW const & rSh )
199{
200 if( SVBT16ToUInt16( rL.lnps ) == 5 ){ // invisible
201 rSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
202 }else{ // visible
203 Color aCol( WW8TransCol( rL.lnpc ) ); // line color
204 rSet.Put( XLineColorItem( OUString(), aCol ) );
205 rSet.Put( XLineWidthItem( SVBT16ToUInt16( rL.lnpw ) ) );
206 // line thickness
207 if( SVBT16ToUInt16( rL.lnps ) >= 1
208 && SVBT16ToUInt16(rL.lnps ) <= 4 ){ // line style
209 rSet.Put( XLineStyleItem( drawing::LineStyle_DASH ) );
210 sal_Int16 nLen = SVBT16ToUInt16( rL.lnpw );
211 XDash aD( css::drawing::DashStyle_RECT, 1, 2 * nLen, 1, 5 * nLen, 5 * nLen );
212 switch( SVBT16ToUInt16( rL.lnps ) ){
213 case 1: aD.SetDots( 0 ); // Dash
214 aD.SetDashLen( 6 * nLen );
215 aD.SetDistance( 4 * nLen );
216 break;
217 case 2: aD.SetDashes( 0 ); break; // Dot
218 case 3: break; // Dash Dot
219 case 4: aD.SetDots( 2 ); break; // Dash Dot Dot
220 }
221 rSet.Put( XLineDashItem( OUString(), aD ) );
222 }else{
223 rSet.Put( XLineStyleItem( drawing::LineStyle_SOLID ) ); // needed for TextBox
224 }
225 }
226 if( SVBT16ToUInt16( rSh.shdwpi ) ){ // shadow
227 rSet.Put(makeSdrShadowItem(true));
228 rSet.Put( makeSdrShadowXDistItem( SVBT16ToUInt16( rSh.xaOffset ) ) );
229 rSet.Put( makeSdrShadowYDistItem( SVBT16ToUInt16( rSh.yaOffset ) ) );
230 }
231}
232
233// SetFill() sets fill attributes such as fore- and background color and
234// pattern by reducing to a color
235// SetFill() doesn't yet set a pattern, because Sdr can't easily do that
236// and the Sdr hatching (XDash) isn't finished yet.
237// Instead, a mixed color will be picked that's between the selected ones.
238static void SetFill( SfxItemSet& rSet, WW8_DP_FILL& rFill )
239{
240 static const sal_uInt8 nPatA[] =
241 {
242 0, 0, 5, 10, 20, 25, 30, 40, 50, 60, 70, 75, 80,
243 90, 50, 50, 50, 50, 50, 50, 33, 33, 33, 33, 33, 33
244 };
245 sal_uInt16 nPat = SVBT16ToUInt16(rFill.flpp);
246
247 if (nPat == 0) // transparent
248 rSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
249 else
250 {
251 rSet.Put(XFillStyleItem(drawing::FillStyle_SOLID)); // necessary for textbox
252 if (nPat <= 1 || (SAL_N_ELEMENTS(nPatA)(sizeof(sal_n_array_size(nPatA))) <= nPat))
253 {
254 // Solid background or unknown
255 rSet.Put(XFillColorItem(OUString(), WW8TransCol(rFill.dlpcBg)));
256 }
257 else
258 { // Brush -> color mix
259 Color aB( WW8TransCol( rFill.dlpcBg ) );
260 Color aF( WW8TransCol( rFill.dlpcFg ) );
261 aB.SetRed( static_cast<sal_uInt8>( ( static_cast<sal_uLong>(aF.GetRed()) * nPatA[nPat]
262 + static_cast<sal_uLong>(aB.GetRed()) * ( 100 - nPatA[nPat] ) ) / 100 ) );
263 aB.SetGreen( static_cast<sal_uInt8>( ( static_cast<sal_uLong>(aF.GetGreen()) * nPatA[nPat]
264 + static_cast<sal_uLong>(aB.GetGreen()) * ( 100 - nPatA[nPat] ) ) / 100 ) );
265 aB.SetBlue( static_cast<sal_uInt8>( ( static_cast<sal_uLong>(aF.GetBlue()) * nPatA[nPat]
266 + static_cast<sal_uLong>(aB.GetBlue()) * ( 100 - nPatA[nPat] ) ) / 100 ) );
267 rSet.Put( XFillColorItem( OUString(), aB ) );
268 }
269 }
270}
271
272static void SetLineEndAttr( SfxItemSet& rSet, WW8_DP_LINEEND const & rLe,
273 WW8_DP_LINETYPE const & rLt )
274{
275 sal_uInt16 aSB = SVBT16ToUInt16( rLe.aStartBits );
276 if( aSB & 0x3 )
277 {
278 ::basegfx::B2DPolygon aPolygon;
279 aPolygon.append(::basegfx::B2DPoint(0.0, 330.0));
280 aPolygon.append(::basegfx::B2DPoint(100.0, 0.0));
281 aPolygon.append(::basegfx::B2DPoint(200.0, 330.0));
282 aPolygon.setClosed(true);
283 rSet.Put( XLineEndItem( OUString(), ::basegfx::B2DPolyPolygon(aPolygon) ) );
284 sal_uInt16 nSiz = SVBT16ToUInt16( rLt.lnpw )
285 * ( ( aSB >> 2 & 0x3 ) + ( aSB >> 4 & 0x3 ) );
286 if( nSiz < 220 ) nSiz = 220;
287 rSet.Put(XLineEndWidthItem(nSiz));
288 rSet.Put(XLineEndCenterItem(false));
289 }
290
291 sal_uInt16 aEB = SVBT16ToUInt16( rLe.aEndBits );
292 if( !(aEB & 0x3) ) return;
293
294 ::basegfx::B2DPolygon aPolygon;
295 aPolygon.append(::basegfx::B2DPoint(0.0, 330.0));
296 aPolygon.append(::basegfx::B2DPoint(100.0, 0.0));
297 aPolygon.append(::basegfx::B2DPoint(200.0, 330.0));
298 aPolygon.setClosed(true);
299 rSet.Put( XLineStartItem( OUString(), ::basegfx::B2DPolyPolygon(aPolygon) ) );
300 sal_uInt16 nSiz = SVBT16ToUInt16( rLt.lnpw )
301 * ( ( aEB >> 2 & 0x3 ) + ( aEB >> 4 & 0x3 ) );
302 if( nSiz < 220 ) nSiz = 220;
303 rSet.Put(XLineStartWidthItem(nSiz));
304 rSet.Put(XLineStartCenterItem(false));
305}
306
307// start of routines for the different objects
308SdrObject* SwWW8ImplReader::ReadLine(WW8_DPHEAD const * pHd, SfxAllItemSet &rSet)
309{
310 WW8_DP_LINE aLine;
311
312 if( !ReadGrafStart( static_cast<void*>(&aLine), sizeof( aLine ), pHd, rSet ) )
313 return nullptr;
314
315 Point aP[2];
316 {
317 Point& rP0 = aP[0];
318 Point& rP1 = aP[1];
319
320 rP0.setX( static_cast<sal_Int16>(SVBT16ToUInt16( pHd->xa )) + m_nDrawXOfs2 );
321 rP0.setY( static_cast<sal_Int16>(SVBT16ToUInt16( pHd->ya )) + m_nDrawYOfs2 );
322 rP1 = rP0;
323 rP0.AdjustX(static_cast<sal_Int16>(SVBT16ToUInt16( aLine.xaStart )) );
324 rP0.AdjustY(static_cast<sal_Int16>(SVBT16ToUInt16( aLine.yaStart )) );
325 rP1.AdjustX(static_cast<sal_Int16>(SVBT16ToUInt16( aLine.xaEnd )) );
326 rP1.AdjustY(static_cast<sal_Int16>(SVBT16ToUInt16( aLine.yaEnd )) );
327 }
328
329 ::basegfx::B2DPolygon aPolygon;
330 aPolygon.append(::basegfx::B2DPoint(aP[0].X(), aP[0].Y()));
331 aPolygon.append(::basegfx::B2DPoint(aP[1].X(), aP[1].Y()));
332 SdrObject* pObj = new SdrPathObj(
333 *m_pDrawModel,
334 OBJ_LINE,
335 ::basegfx::B2DPolyPolygon(aPolygon));
336
337 SetStdAttr( rSet, aLine.aLnt, aLine.aShd );
338 SetLineEndAttr( rSet, aLine.aEpp, aLine.aLnt );
339
340 return pObj;
341}
342
343SdrObject* SwWW8ImplReader::ReadRect(WW8_DPHEAD const * pHd, SfxAllItemSet &rSet)
344{
345 WW8_DP_RECT aRect;
346
347 if( !ReadGrafStart( static_cast<void*>(&aRect), sizeof( aRect ), pHd, rSet ) )
348 return nullptr;
349
350 Point aP0( static_cast<sal_Int16>(SVBT16ToUInt16( pHd->xa )) + m_nDrawXOfs2,
351 static_cast<sal_Int16>(SVBT16ToUInt16( pHd->ya )) + m_nDrawYOfs2 );
352 Point aP1( aP0 );
353 aP1.AdjustX(static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dxa )) );
354 aP1.AdjustY(static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dya )) );
355
356 SdrObject* pObj = new SdrRectObj(
357 *m_pDrawModel,
358 tools::Rectangle(aP0, aP1));
359
360 SetStdAttr( rSet, aRect.aLnt, aRect.aShd );
361 SetFill( rSet, aRect.aFill );
362
363 return pObj;
364}
365
366SdrObject* SwWW8ImplReader::ReadEllipse(WW8_DPHEAD const * pHd, SfxAllItemSet &rSet)
367{
368 WW8_DP_ELLIPSE aEllipse;
369
370 if( !ReadGrafStart( static_cast<void*>(&aEllipse), sizeof( aEllipse ), pHd, rSet ) )
371 return nullptr;
372
373 Point aP0( static_cast<sal_Int16>(SVBT16ToUInt16( pHd->xa )) + m_nDrawXOfs2,
374 static_cast<sal_Int16>(SVBT16ToUInt16( pHd->ya )) + m_nDrawYOfs2 );
375 Point aP1( aP0 );
376 aP1.AdjustX(static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dxa )) );
377 aP1.AdjustY(static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dya )) );
378
379 SdrObject* pObj = new SdrCircObj(
380 *m_pDrawModel,
381 SdrCircKind::Full,
382 tools::Rectangle(aP0, aP1));
383
384 SetStdAttr( rSet, aEllipse.aLnt, aEllipse.aShd );
385 SetFill( rSet, aEllipse.aFill );
386
387 return pObj;
388}
389
390SdrObject* SwWW8ImplReader::ReadArc(WW8_DPHEAD const * pHd, SfxAllItemSet &rSet)
391{
392 WW8_DP_ARC aArc;
393
394 if( !ReadGrafStart( static_cast<void*>(&aArc), sizeof( aArc ), pHd, rSet ) )
395 return nullptr;
396
397 Point aP0( static_cast<sal_Int16>(SVBT16ToUInt16( pHd->xa )) + m_nDrawXOfs2,
398 static_cast<sal_Int16>(SVBT16ToUInt16( pHd->ya )) + m_nDrawYOfs2 );
399 Point aP1( aP0 );
400 aP1.AdjustX(static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dxa )) * 2 );
401 aP1.AdjustY(static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dya )) * 2 );
402
403 short nA[] = { 2, 3, 1, 0 };
404 short nW = nA[ ( ( aArc.fLeft & 1 ) << 1 ) + ( aArc.fUp & 1 ) ];
405 if( !aArc.fLeft ){
406 aP0.AdjustY( -static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dya )) );
407 aP1.AdjustY( -static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dya )) );
408 }
409 if( aArc.fUp ){
410 aP0.AdjustX( -static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dxa )) );
411 aP1.AdjustX( -static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dxa )) );
412 }
413
414 SdrObject* pObj = new SdrCircObj(
415 *m_pDrawModel,
416 SdrCircKind::Section,
417 tools::Rectangle(aP0, aP1),
418 nW * 9000,
419 ( ( nW + 1 ) & 3 ) * 9000);
420
421 SetStdAttr( rSet, aArc.aLnt, aArc.aShd );
422 SetFill( rSet, aArc.aFill );
423
424 return pObj;
425}
426
427SdrObject* SwWW8ImplReader::ReadPolyLine(WW8_DPHEAD const * pHd, SfxAllItemSet &rSet)
428{
429 WW8_DP_POLYLINE aPoly;
430
431 if( !ReadGrafStart( static_cast<void*>(&aPoly), sizeof( aPoly ), pHd, rSet ) )
432 return nullptr;
433
434 sal_uInt16 nCount = SVBT16ToUInt16( aPoly.aBits1 ) >> 1 & 0x7fff;
435 std::unique_ptr<SVBT16[]> xP(new SVBT16[nCount * 2]);
436
437 bool bCouldRead = checkRead(*m_pStrm, xP.get(), nCount * 4); // read points
438 OSL_ENSURE(bCouldRead, "Short PolyLine header")do { if (true && (!(bCouldRead))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "438" ": "), "%s", "Short PolyLine header"); } } while (
false)
;
439 if (!bCouldRead)
440 return nullptr;
441
442 tools::Polygon aP( nCount );
443 Point aPt;
444 for (sal_uInt16 i=0; i<nCount; ++i)
445 {
446 aPt.setX( SVBT16ToUInt16( xP[i << 1] ) + m_nDrawXOfs2
447 + static_cast<sal_Int16>(SVBT16ToUInt16( pHd->xa )) );
448 aPt.setY( SVBT16ToUInt16( xP[( i << 1 ) + 1] ) + m_nDrawYOfs2
449 + static_cast<sal_Int16>(SVBT16ToUInt16( pHd->ya )) );
450 aP[i] = aPt;
451 }
452 xP.reset();
453
454 SdrObject* pObj = new SdrPathObj(
455 *m_pDrawModel,
456 (SVBT16ToUInt16(aPoly.aBits1) & 0x1) ? OBJ_POLY : OBJ_PLIN,
457 ::basegfx::B2DPolyPolygon(aP.getB2DPolygon()));
458
459 SetStdAttr( rSet, aPoly.aLnt, aPoly.aShd );
460 SetFill( rSet, aPoly.aFill );
461
462 return pObj;
463}
464
465static ESelection GetESelection(EditEngine const &rDrawEditEngine, long nCpStart, long nCpEnd)
466{
467 sal_Int32 nPCnt = rDrawEditEngine.GetParagraphCount();
468 sal_Int32 nSP = 0;
469 sal_Int32 nEP = 0;
470 while( (nSP < nPCnt)
471 && (nCpStart >= rDrawEditEngine.GetTextLen( nSP ) + 1) )
472 {
473 nCpStart -= rDrawEditEngine.GetTextLen( nSP ) + 1;
474 nSP++;
475 }
476 // at the end, switch to the new line only 1 character later as
477 // otherwise line attributes reach one line too far
478 while( (nEP < nPCnt)
479 && (nCpEnd > rDrawEditEngine.GetTextLen( nEP ) + 1) )
480 {
481 nCpEnd -= rDrawEditEngine.GetTextLen( nEP ) + 1;
482 nEP++;
483 }
484 return ESelection( nSP, nCpStart, nEP, nCpEnd );
485}
486
487// InsertTxbxStyAttrs() sets style attributes into the passed ItemSet.
488// SW styles are used since import-WW-styles are already destroyed.
489// SW styles are examined in depth first search order (with parent styles)
490// for the attributes given in aSrcTab. They're cloned, and the clones'
491// Which-IDs are changed according to the aDstTab table so that the
492// EditEngine will not ignore them.
493// Both Paragraph and character attributes are stuffed into the ItemSet.
494void SwWW8ImplReader::InsertTxbxStyAttrs( SfxItemSet& rS, sal_uInt16 nColl )
495{
496 SwWW8StyInf * pStyInf = GetStyle(nColl);
497 if( !(pStyInf != nullptr && pStyInf->m_pFormat && pStyInf->m_bColl) )
498 return;
499
500 const SfxPoolItem* pItem;
501 for( sal_uInt16 i = POOLATTR_BEGIN; i < POOLATTR_END; i++ )
502 {
503 // If we are set in the source and not set in the destination
504 // then add it in.
505 if ( SfxItemState::SET == pStyInf->m_pFormat->GetItemState(
506 i, true, &pItem ) )
507 {
508 SfxItemPool *pEditPool = rS.GetPool();
509 sal_uInt16 nWhich = i;
510 sal_uInt16 nSlotId = m_rDoc.GetAttrPool().GetSlotId(nWhich);
511 if (
512 nSlotId && nWhich != nSlotId &&
513 0 != (nWhich = pEditPool->GetWhich(nSlotId)) &&
514 nWhich != nSlotId &&
515 ( SfxItemState::SET != rS.GetItemState(nWhich, false) )
516 )
517 {
518 rS.Put( pItem->CloneSetWhich(nWhich) );
519 }
520 }
521 }
522
523}
524
525static void lcl_StripFields(OUString &rString, WW8_CP &rNewStartCp)
526{
527 sal_Int32 nStartPos = 0;
528 for (;;)
529 {
530 nStartPos = rString.indexOf(0x13, nStartPos);
531 if (nStartPos<0)
532 return;
533
534 const sal_Unicode cStops[] = {0x14, 0x15, 0};
535 const sal_Int32 nStopPos = comphelper::string::indexOfAny(rString, cStops, nStartPos);
536 if (nStopPos<0)
537 {
538 rNewStartCp += rString.getLength()-nStartPos;
539 rString = rString.copy(0, nStartPos);
540 return;
541 }
542
543 const bool was0x14 = rString[nStopPos]==0x14;
544 rString = rString.replaceAt(nStartPos, nStopPos+1-nStartPos, "");
545 rNewStartCp += nStopPos-nStartPos;
546
547 if (was0x14)
548 {
549 ++rNewStartCp;
550 nStartPos = rString.indexOf(0x15, nStartPos);
551 if (nStartPos<0)
552 return;
553 rString = rString.replaceAt(nStartPos, 1, "");
554 }
555 }
556}
557
558namespace {
559
560class Chunk
561{
562private:
563 OUString msURL;
564 long mnStartPos; // 0x13
565 long mnEndPos; // 0x15
566public:
567 explicit Chunk(long nStart, const OUString &rURL)
568 : msURL(rURL), mnStartPos(nStart), mnEndPos(0) {}
569
570 void SetEndPos(long nEnd) { mnEndPos = nEnd; }
571 long GetStartPos() const {return mnStartPos;}
572 long GetEndPos() const {return mnEndPos;}
573 const OUString &GetURL() const {return msURL;}
574 void Adjust(sal_Int32 nAdjust)
575 {
576 mnStartPos-=nAdjust;
577 mnEndPos-=nAdjust;
578 }
579};
580
581 bool IsValidSel(const EditEngine& rEngine, const ESelection& rSel)
582 {
583 const auto nParaCount = rEngine.GetParagraphCount();
584 if (rSel.nStartPara < nParaCount && rSel.nEndPara < nParaCount)
585 return rSel.nStartPos >= 0 && rSel.nEndPos >= 0;
586 return false;
587 }
588}
589
590// InsertAttrsAsDrawingAttrs() sets attributes between StartCp and EndCp.
591// Style attributes are set as hard, paragraph and character attributes.
592void SwWW8ImplReader::InsertAttrsAsDrawingAttrs(WW8_CP nStartCp, WW8_CP nEndCp,
593 ManTypes eType, bool bONLYnPicLocFc)
594{
595 /*
596 Save and create new plcxman for this drawing object, of the type that
597 will include the para end mark inside a paragraph property range, as
598 drawing boxes have real paragraph marks as part of their text, while
599 normal writer has separate nodes for each paragraph and so has no actual
600 paragraph mark as part of the paragraph text.
601 */
602 WW8ReaderSave aSave(this);
603 m_xPlcxMan = std::make_shared<WW8PLCFMan>(m_xSBase.get(), eType, nStartCp, true);
604
605 WW8_CP nStart = m_xPlcxMan->Where();
606 WW8_CP nNext, nStartReplace=0;
607
608 bool bDoingSymbol = false;
609 sal_Unicode cReplaceSymbol = m_cSymbol;
610
611 std::unique_ptr<SfxItemSet> pS(new SfxItemSet(m_pDrawEditEngine->GetEmptyItemSet()));
612 WW8PLCFManResult aRes;
613
614 std::deque<Chunk> aChunks;
615
616 // Here store stack location
617 size_t nCurrentCount = m_xCtrlStck->size();
618 while (nStart < nEndCp)
619 {
620 // nStart is the beginning of the attributes for this range, and
621 // may be before the text itself. So watch out for that
622 WW8_CP nTextStart = nStart;
623 if (nTextStart < nStartCp)
624 nTextStart = nStartCp;
625
626 // get position of next SPRM
627 bool bStartAttr = m_xPlcxMan->Get(&aRes);
628 m_nCurrentColl = m_xPlcxMan->GetColl();
629 if (aRes.nSprmId)
630 {
631 if( bONLYnPicLocFc )
632 {
633 if ( (68 == aRes.nSprmId) || (0x6A03 == aRes.nSprmId) )
634 {
635 Read_PicLoc(aRes.nSprmId, aRes.pMemPos +
636 m_xSprmParser->DistanceToData(aRes.nSprmId), 4);
637 // Ok, that's what we were looking for. Now let's get
638 // out of here!
639 break;
640 }
641 }
642 else if ((eFTN > aRes.nSprmId) || (0x0800 <= aRes.nSprmId))
643 {
644 // Here place them onto our usual stack and we will pop them
645 // off and convert them later
646 if (bStartAttr)
647 {
648 ImportSprm(aRes.pMemPos, aRes.nMemLen, aRes.nSprmId);
649 if (!bDoingSymbol && m_bSymbol)
650 {
651 bDoingSymbol = true;
652 nStartReplace = nTextStart;
653 cReplaceSymbol = m_cSymbol;
654 }
655 }
656 else
657 {
658 EndSprm( aRes.nSprmId );
659 if (!m_bSymbol && bDoingSymbol)
660 {
661 bDoingSymbol = false;
662 OUStringBuffer sTemp;
663 comphelper::string::padToLength(sTemp,
664 nTextStart - nStartReplace, cReplaceSymbol);
665 m_pDrawEditEngine->QuickInsertText(sTemp.makeStringAndClear(),
666 GetESelection(*m_pDrawEditEngine, nStartReplace - nStartCp,
667 nTextStart - nStartCp ) );
668 }
669 }
670 }
671 else if (aRes.nSprmId == eFLD)
672 {
673 if (bStartAttr)
674 {
675 size_t nCount = m_xCtrlStck->size();
676 if (m_aFieldStack.empty() && Read_Field(&aRes))
677 {
678 OUString sURL;
679 for (size_t nI = m_xCtrlStck->size(); nI > nCount; --nI)
680 {
681 const SfxPoolItem *pItem = ((*m_xCtrlStck)[nI-1]).pAttr.get();
682 sal_uInt16 nWhich = pItem->Which();
683 if (nWhich == RES_TXTATR_INETFMT)
684 {
685 const SwFormatINetFormat *pURL =
686 static_cast<const SwFormatINetFormat *>(pItem);
687 sURL = pURL->GetValue();
688 }
689 m_xCtrlStck->DeleteAndDestroy(nI-1);
690 }
691 aChunks.emplace_back(nStart, sURL);
692 }
693 }
694 else
695 {
696 if (!m_aFieldStack.empty() && End_Field() && !aChunks.empty())
697 aChunks.back().SetEndPos(nStart+1);
698 }
699 }
700 }
701
702 m_xPlcxMan->advance();
703 nNext = m_xPlcxMan->Where();
704
705 const WW8_CP nEnd = ( nNext < nEndCp ) ? nNext : nEndCp;
706 if (!bONLYnPicLocFc && nNext != nStart && nEnd >= nStartCp)
707 {
708 SfxItemPool *pEditPool = pS->GetPool();
709
710 // Here read current properties and convert them into pS
711 // and put those attrs into the draw box if they can be converted
712 // to draw attributes
713 if (m_xCtrlStck->size() - nCurrentCount)
714 {
715 for (size_t i = nCurrentCount; i < m_xCtrlStck->size(); ++i)
716 {
717 const SfxPoolItem *pItem = ((*m_xCtrlStck)[i]).pAttr.get();
718 sal_uInt16 nWhich = pItem->Which();
719 if( nWhich < RES_FLTRATTR_BEGIN ||
720 nWhich >= RES_FLTRATTR_END )
721 {
722 sal_uInt16 nSlotId = m_rDoc.GetAttrPool().GetSlotId(nWhich);
723 if (
724 nSlotId && nWhich != nSlotId &&
725 0 != (nWhich = pEditPool->GetWhich(nSlotId)) &&
726 nWhich != nSlotId
727 )
728 {
729 pS->Put( pItem->CloneSetWhich(nWhich) );
730 }
731 }
732 }
733 }
734 // Fill in the remainder from the style
735 InsertTxbxStyAttrs(*pS, m_nCurrentColl);
736
737 if( pS->Count() )
738 {
739 m_pDrawEditEngine->QuickSetAttribs( *pS,
740 GetESelection(*m_pDrawEditEngine, nTextStart - nStartCp, nEnd - nStartCp ) );
741 pS.reset( new SfxItemSet(m_pDrawEditEngine->GetEmptyItemSet()) );
742 }
743 }
744 nStart = nNext;
745 }
746 pS.reset();
747
748 // pop off as far as recorded location just in case there were some left
749 // unclosed
750 for (size_t nI = m_xCtrlStck->size(); nI > nCurrentCount; --nI)
751 m_xCtrlStck->DeleteAndDestroy(nI-1);
752
753 auto aEnd = aChunks.end();
754 for (auto aIter = aChunks.begin(); aIter != aEnd; ++aIter)
755 {
756 ESelection aSel(GetESelection(*m_pDrawEditEngine, aIter->GetStartPos()-nStartCp,
757 aIter->GetEndPos()-nStartCp));
758 if (!IsValidSel(*m_pDrawEditEngine, aSel))
759 continue;
760 OUString aString(m_pDrawEditEngine->GetText(aSel));
761 const sal_Int32 nOrigLen = aString.getLength();
762 WW8_CP nDummy(0);
763 lcl_StripFields(aString, nDummy);
764
765 sal_Int32 nChanged;
766 if (!aIter->GetURL().isEmpty())
767 {
768 SvxURLField aURL(aIter->GetURL(), aString, SvxURLFormat::AppDefault);
769 m_pDrawEditEngine->QuickInsertField(SvxFieldItem(aURL, EE_FEATURE_FIELD), aSel);
770 nChanged = nOrigLen - 1;
771 }
772 else
773 {
774 m_pDrawEditEngine->QuickInsertText(aString, aSel);
775 nChanged = nOrigLen - aString.getLength();
776 }
777 for (auto aIter2 = aIter+1; aIter2 != aEnd; ++aIter2)
778 aIter2->Adjust(nChanged);
779 }
780
781 /*
782 Don't worry about the new pPlcxMan, the restore removes it when
783 replacing the current one with the old one.
784 */
785 aSave.Restore(this);
786}
787
788bool SwWW8ImplReader::GetTxbxTextSttEndCp(WW8_CP& rStartCp, WW8_CP& rEndCp,
789 sal_uInt16 nTxBxS, sal_uInt16 nSequence)
790{
791 // grab the TextBox-PLCF quickly
792 WW8PLCFspecial* pT = m_xPlcxMan ? m_xPlcxMan->GetTxbx() : nullptr;
5
'?' condition is true
793 if( !pT )
6
Assuming 'pT' is null
7
Taking true branch
794 {
795 OSL_ENSURE( false, "+where's the text graphic (1)?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "795" ": "), "%s", "+where's the text graphic (1)?"); } }
while (false)
;
8
Taking true branch
9
Loop condition is false. Exiting loop
796 return false;
10
Returning without writing to 'rEndCp'
797 }
798
799 // if applicable first find the right TextBox-Story
800 bool bCheckTextBoxStory = ( nTxBxS && pT->GetIMax() >= nTxBxS );
801 if( bCheckTextBoxStory )
802 pT->SetIdx( nTxBxS-1 );
803
804 // then determine start and end
805 void* pT0;
806 if (!pT->Get(rStartCp, pT0) || rStartCp < 0)
807 {
808 OSL_ENSURE( false, "+where's the text graphic (2)?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "808" ": "), "%s", "+where's the text graphic (2)?"); } }
while (false)
;
809 return false;
810 }
811
812 if( bCheckTextBoxStory )
813 {
814 bool bReusable = (0 != SVBT16ToUInt16( static_cast<WW8_TXBXS*>(pT0)->fReusable ));
815 while( bReusable )
816 {
817 pT->advance();
818 if( !pT->Get( rStartCp, pT0 ) )
819 {
820 OSL_ENSURE( false, "+where's the text graphic (2a)?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "820" ": "), "%s", "+where's the text graphic (2a)?"); }
} while (false)
;
821 return false;
822 }
823 bReusable = (0 != SVBT16ToUInt16( static_cast<WW8_TXBXS*>(pT0)->fReusable ));
824 }
825 }
826 pT->advance();
827 if (!pT->Get(rEndCp, pT0) || rEndCp < 0)
828 {
829 OSL_ENSURE( false, "+where's the text graphic (3)?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "829" ": "), "%s", "+where's the text graphic (3)?"); } }
while (false)
;
830 return false;
831 }
832
833 // find the right page in the break table (if necessary)
834 if( bCheckTextBoxStory )
835 {
836 // special case: entire chain should be determined - done!
837 if( USHRT_MAX(32767 *2 +1) > nSequence )
838 {
839 long nMinStartCp = rStartCp;
840 long nMaxEndCp = rEndCp;
841 // quickly grab the TextBox-Break-Descriptor-PLCF
842 pT = m_xPlcxMan->GetTxbxBkd();
843 if (!pT) // It can occur on occasion, Caolan
844 return false;
845
846 // find first entry for this TextBox story
847 if( !pT->SeekPos( rStartCp ) )
848 {
849 OSL_ENSURE( false, "+where's the text graphic (4)" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "849" ": "), "%s", "+where's the text graphic (4)"); } }
while (false)
;
850 return false;
851 }
852 // if needed skip the appropriate number of entries
853 for (sal_uInt16 iSequence = 0; iSequence < nSequence; ++iSequence)
854 pT->advance();
855 // and determine actual start and end
856 if( (!pT->Get( rStartCp, pT0 ))
857 || ( nMinStartCp > rStartCp ) )
858 {
859 OSL_ENSURE( false, "+where's the text graphic (5)?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "859" ": "), "%s", "+where's the text graphic (5)?"); } }
while (false)
;
860 return false;
861 }
862 if( rStartCp >= nMaxEndCp )
863 rEndCp = rStartCp; // not an error: empty string
864 else
865 {
866 pT->advance();
867 if ( (!pT->Get(rEndCp, pT0)) || (nMaxEndCp < rEndCp-1) )
868 {
869 OSL_ENSURE( false, "+where's the text graphic (6)?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "869" ": "), "%s", "+where's the text graphic (6)?"); } }
while (false)
;
870 return false;
871 }
872 rEndCp -= 1;
873 }
874 }
875 else
876 rEndCp -= 1;
877 }
878 else
879 rEndCp -= 1;
880 return true;
881}
882
883// TxbxText() grabs the text from the WW file and returns that along with
884// the StartCp and the corrected (by -2, or -1 for version 8) EndCp.
885sal_Int32 SwWW8ImplReader::GetRangeAsDrawingString(OUString& rString, long nStartCp, long nEndCp, ManTypes eType)
886{
887 WW8_CP nOffset = 0;
888 m_xWwFib->GetBaseCp(eType, &nOffset); //TODO: check return value
889
890 OSL_ENSURE(nStartCp <= nEndCp, "+where's the graphic text (7)?")do { if (true && (!(nStartCp <= nEndCp))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "890" ": "), "%s", "+where's the graphic text (7)?"); } }
while (false)
;
891 if (nStartCp == nEndCp)
892 rString.clear(); // empty string: entirely possible
893 else if (nStartCp < nEndCp)
894 {
895 // read the text: can be split into multiple pieces
896 const sal_Int32 nLen = m_xSBase->WW8ReadString(*m_pStrm, rString,
897 nStartCp + nOffset, nEndCp - nStartCp, GetCurrentCharSet());
898 OSL_ENSURE(nLen, "+where's the text graphic (8)?")do { if (true && (!(nLen))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "898" ": "), "%s", "+where's the text graphic (8)?"); } }
while (false)
;
899 if (nLen>0)
900 {
901 if( rString[nLen-1]==0x0d )
902 rString = rString.copy(0, nLen-1);
903
904 rString = rString.replace( 0xb, 0xa );
905 return nLen;
906 }
907 }
908 return 0;
909}
910
911//EditEngine::InsertText will replace dos lines resulting in a shorter
912//string than is passed in, so inserting attributes based on the original
913//string len can fail. So here replace the dos line ends similar to
914//how EditEngine does it, but preserve the length and replace the extra
915//chars with placeholders, record the position of the placeholders and
916//remove those extra chars after attributes have been inserted
917static std::vector<sal_Int32> replaceDosLineEndsButPreserveLength(OUString &rIn)
918{
919 OUStringBuffer aNewData(rIn);
920 std::vector<sal_Int32> aDosLineEndDummies;
921 sal_Int32 i = 0;
922 sal_Int32 nStrLen = rIn.getLength();
923 while (i < nStrLen)
924 {
925 // \r or \n causes linebreak
926 if (rIn[i] == '\r' || rIn[i] == '\n')
927 {
928 // skip char if \r\n or \n\r
929 if ( (i+1) < nStrLen && ((rIn[i+1] == '\r') || (rIn[i+1] == '\n')) &&
930 (rIn[i] != rIn[i+1]) )
931 {
932 ++i;
933 aDosLineEndDummies.push_back(i);
934 aNewData[i] = 0;
935 }
936 }
937 ++i;
938 }
939 rIn = aNewData.makeStringAndClear();
940 return aDosLineEndDummies;
941}
942
943static void removePositions(EditEngine &rDrawEditEngine, const std::vector<sal_Int32>& rDosLineEndDummies)
944{
945 for (auto aIter = rDosLineEndDummies.rbegin(); aIter != rDosLineEndDummies.rend(); ++aIter)
946 {
947 sal_Int32 nCharPos(*aIter);
948 rDrawEditEngine.QuickDelete(GetESelection(rDrawEditEngine, nCharPos, nCharPos+1));
949 }
950}
951
952std::unique_ptr<OutlinerParaObject> SwWW8ImplReader::ImportAsOutliner(OUString &rString, WW8_CP nStartCp, WW8_CP nEndCp, ManTypes eType)
953{
954 std::unique_ptr<OutlinerParaObject> pRet;
955
956 sal_Int32 nLen = GetRangeAsDrawingString(rString, nStartCp, nEndCp, eType);
957 if (nLen > 0)
958 {
959 if (!m_pDrawEditEngine)
960 {
961 m_pDrawEditEngine.reset(new EditEngine(nullptr));
962 }
963
964 //replace dos line endings with editeng ones, replace any extra chars with
965 //placeholders to keep the inserted string len in sync with the attribute cps
966 //and record in aDosLineEnds the superfluous positions
967 OUString sEEString(rString);
968 std::vector<sal_Int32> aDosLineEnds(replaceDosLineEndsButPreserveLength(sEEString));
969 m_pDrawEditEngine->SetText(sEEString);
970 InsertAttrsAsDrawingAttrs(nStartCp, nStartCp+nLen, eType);
971 //remove any superfluous placeholders of replaceDosLineEndsButPreserveLength
972 //after attributes have been inserted
973 removePositions(*m_pDrawEditEngine, aDosLineEnds);
974
975 // Annotations typically begin with a (useless) 0x5
976 if ((eType == MAN_AND) && m_pDrawEditEngine->GetTextLen())
977 {
978 ESelection aFirstChar(0, 0, 0, 1);
979 if (m_pDrawEditEngine->GetText( aFirstChar ) == "\x05")
980 m_pDrawEditEngine->QuickDelete(aFirstChar);
981 }
982
983 std::unique_ptr<EditTextObject> pTemporaryText = m_pDrawEditEngine->CreateTextObject();
984 pRet.reset( new OutlinerParaObject( std::move(pTemporaryText) ) );
985 pRet->SetOutlinerMode( OutlinerMode::TextObject );
986
987 m_pDrawEditEngine->SetText( OUString() );
988 m_pDrawEditEngine->SetParaAttribs(0, m_pDrawEditEngine->GetEmptyItemSet());
989
990 // Strip out fields, leaving the result
991 WW8_CP nDummy(0);
992 lcl_StripFields(rString, nDummy);
993 // Strip out word's special characters for the simple string
994 rString = rString.replaceAll("\x01", "");
995 rString = rString.replaceAll("\x05", "");
996 rString = rString.replaceAll("\x08", "");
997 rString = rString.replaceAll("\007\007", "\007\012");
998 rString = rString.replace(0x7, ' ');
999 }
1000
1001 return pRet;
1002}
1003
1004// InsertTxbxText() adds the Text and the Attributes for TextBoxes and CaptionBoxes
1005void SwWW8ImplReader::InsertTxbxText(SdrTextObj* pTextObj,
1006 Size const * pObjSiz, sal_uInt16 nTxBxS, sal_uInt16 nSequence, long nPosCp,
1007 SwFrameFormat const * pOldFlyFormat, bool bMakeSdrGrafObj, bool& rbEraseTextObj,
1008 bool* pbTestTxbxContainsText, long* pnStartCp, long* pnEndCp,
1009 bool* pbContainsGraphics, SvxMSDffImportRec const * pRecord)
1010{
1011 SwFrameFormat* pFlyFormat = nullptr;
1012 sal_uLong nOld = m_pStrm->Tell();
1013
1014 ManTypes eType = m_xPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX;
1
Assuming the condition is false
2
'?' condition is false
1015
1016 rbEraseTextObj = false;
1017
1018 OUString aString;
1019 WW8_CP nStartCp, nEndCp;
3
'nEndCp' declared without an initial value
1020 bool bContainsGraphics = false;
1021 bool bTextWasRead = GetTxbxTextSttEndCp(nStartCp, nEndCp, nTxBxS, nSequence) &&
4
Calling 'SwWW8ImplReader::GetTxbxTextSttEndCp'
11
Returning from 'SwWW8ImplReader::GetTxbxTextSttEndCp'
1022 GetRangeAsDrawingString(aString, nStartCp, nEndCp, eType) > 0;
1023
1024 if (!m_pDrawEditEngine)
12
Taking false branch
1025 {
1026 m_pDrawEditEngine.reset(new EditEngine(nullptr));
1027 }
1028 if( pObjSiz )
13
Assuming 'pObjSiz' is null
14
Taking false branch
1029 m_pDrawEditEngine->SetPaperSize( *pObjSiz );
1030
1031 const OUString aOrigString(aString);
1032 if( bTextWasRead
14.1
'bTextWasRead' is false
)
15
Taking false branch
1033 {
1034 WW8_CP nNewStartCp = nStartCp;
1035 lcl_StripFields(aString, nNewStartCp);
1036
1037 if (aString.getLength()!=1)
1038 {
1039 bContainsGraphics = aString.indexOf(0x1)<0 || aString.indexOf(0x8)<0;
1040 }
1041 else // May be a single graphic or object
1042 {
1043 bool bDone = true;
1044 switch( aString[0] )
1045 {
1046 case 0x1:
1047 if (!pbTestTxbxContainsText)
1048 {
1049 WW8ReaderSave aSave(this, nNewStartCp -1);
1050 bool bOldEmbeddObj = m_bEmbeddObj;
1051 // bEmbeddObj Ordinarily would have been set by field
1052 // parse, but this is impossible here so...
1053 m_bEmbeddObj = true;
1054
1055 // 1st look for OLE- or Graph-Indicator Sprms
1056 WW8PLCFx_Cp_FKP* pChp = m_xPlcxMan->GetChpPLCF();
1057 WW8PLCFxDesc aDesc;
1058 pChp->GetSprms( &aDesc );
1059 WW8SprmIter aSprmIter(aDesc.pMemPos, aDesc.nSprmsLen, *m_xSprmParser);
1060
1061 for( int nLoop = 0; nLoop < 2; ++nLoop )
1062 {
1063 while (aSprmIter.GetSprms())
1064 {
1065 const sal_uInt8 *const pParams(aSprmIter.GetCurrentParams());
1066 if (nullptr == pParams)
1067 break;
1068 sal_uInt16 nCurrentId = aSprmIter.GetCurrentId();
1069 switch( nCurrentId )
1070 {
1071 case 75:
1072 case 118:
1073 case 0x080A:
1074 case 0x0856:
1075 Read_Obj(nCurrentId, pParams, 1);
1076 break;
1077 case 68: // Read_Pic()
1078 case 0x6A03:
1079 case NS_sprm::LN_CObjLocation:
1080 Read_PicLoc(nCurrentId, pParams, 1);
1081 break;
1082 }
1083 aSprmIter.advance();
1084 }
1085
1086 if( !nLoop )
1087 {
1088 pChp->GetPCDSprms( aDesc );
1089 aSprmIter.SetSprms( aDesc.pMemPos,
1090 aDesc.nSprmsLen );
1091 }
1092 }
1093 aSave.Restore(this);
1094 m_bEmbeddObj=bOldEmbeddObj;
1095
1096 // then import either an OLE of a Graphic
1097 if( m_bObj )
1098 {
1099 if( bMakeSdrGrafObj && pTextObj &&
1100 pTextObj->getParentSdrObjectFromSdrObject() )
1101 {
1102 // use SdrOleObj/SdrGrafObj instead of
1103 // SdrTextObj in this Group
1104
1105 Graphic aGraph;
1106 SdrObject* pNew = ImportOleBase(aGraph);
1107
1108 if( !pNew )
1109 {
1110 pNew = new SdrGrafObj(*m_pDrawModel);
1111 static_cast<SdrGrafObj*>(pNew)->SetGraphic(aGraph);
1112 }
1113
1114 GrafikCtor();
1115
1116 pNew->SetLogicRect( pTextObj->GetCurrentBoundRect() );
1117 pNew->SetLayer( pTextObj->GetLayer() );
1118
1119 pTextObj->getParentSdrObjectFromSdrObject()->GetSubList()->
1120 ReplaceObject(pNew, pTextObj->GetOrdNum());
1121 }
1122 else
1123 pFlyFormat = ImportOle();
1124 m_bObj = false;
1125 }
1126 else
1127 {
1128 InsertAttrsAsDrawingAttrs(nNewStartCp, nNewStartCp+1,
1129 eType, true);
1130 pFlyFormat = ImportGraf(bMakeSdrGrafObj ? pTextObj : nullptr,
1131 pOldFlyFormat);
1132 }
1133 }
1134 break;
1135 case 0x8:
1136 if ( (!pbTestTxbxContainsText) && (!m_bObj) )
1137 pFlyFormat = Read_GrafLayer( nPosCp );
1138 break;
1139 default:
1140 bDone = false;
1141 break;
1142 }
1143
1144 if( bDone )
1145 {
1146 if( pFlyFormat && pRecord )
1147 {
1148 SfxItemSet aFlySet( m_rDoc.GetAttrPool(),
1149 svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1, XATTR_START, XATTR_END>{} );
1150
1151 tools::Rectangle aInnerDist( pRecord->nDxTextLeft,
1152 pRecord->nDyTextTop,
1153 pRecord->nDxTextRight,
1154 pRecord->nDyTextBottom );
1155 MatchSdrItemsIntoFlySet( pTextObj,
1156 aFlySet,
1157 pRecord->eLineStyle,
1158 pRecord->eLineDashing,
1159 pRecord->eShapeType,
1160 aInnerDist );
1161
1162 pFlyFormat->SetFormatAttr( aFlySet );
1163
1164 MapWrapIntoFlyFormat(pRecord, pFlyFormat);
1165 }
1166 aString.clear();
1167 rbEraseTextObj = (nullptr != pFlyFormat);
1168 }
1169 }
1170 }
1171
1172 if( pnStartCp )
16
Assuming 'pnStartCp' is null
17
Taking false branch
1173 *pnStartCp = nStartCp;
1174 if( pnEndCp )
18
Assuming 'pnEndCp' is non-null
19
Taking true branch
1175 *pnEndCp = nEndCp;
20
Assigned value is garbage or undefined
1176
1177 if( pbTestTxbxContainsText )
1178 *pbTestTxbxContainsText = bTextWasRead && ! rbEraseTextObj;
1179 else if( !rbEraseTextObj )
1180 {
1181 if( bTextWasRead )
1182 {
1183 m_pDrawEditEngine->SetText(aOrigString);
1184 InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType);
1185 }
1186
1187 bool bVertical = pTextObj->IsVerticalWriting();
1188 std::unique_ptr<EditTextObject> pTemporaryText = m_pDrawEditEngine->CreateTextObject();
1189 std::unique_ptr<OutlinerParaObject> pOp( new OutlinerParaObject(*pTemporaryText) );
1190 pOp->SetOutlinerMode( OutlinerMode::TextObject );
1191 pOp->SetVertical( bVertical );
1192 pTemporaryText.reset();
1193 pTextObj->NbcSetOutlinerParaObject( std::move(pOp) );
1194 pTextObj->SetVerticalWriting(bVertical);
1195
1196 // For the next TextBox also remove the old paragraph attributes
1197 // and styles, otherwise the next box will start with the wrong
1198 // attributes.
1199 // Course of action: delete text = reduce to one paragraph
1200 // and on this one delete the paragraph attributes
1201 // and styles
1202 m_pDrawEditEngine->SetText( OUString() );
1203 m_pDrawEditEngine->SetParaAttribs(0, m_pDrawEditEngine->GetEmptyItemSet());
1204 }
1205
1206 m_pStrm->Seek( nOld );
1207 if (pbContainsGraphics)
1208 *pbContainsGraphics = bContainsGraphics;
1209}
1210
1211bool SwWW8ImplReader::TxbxChainContainsRealText(sal_uInt16 nTxBxS, long& rStartCp,
1212 long& rEndCp)
1213{
1214 bool bErase, bContainsText;
1215 InsertTxbxText( nullptr,nullptr,nTxBxS,USHRT_MAX(32767 *2 +1),0,nullptr,false, bErase, &bContainsText,
1216 &rStartCp, &rEndCp );
1217 return bContainsText;
1218}
1219
1220// TextBoxes only for Ver67 !!
1221SdrObject* SwWW8ImplReader::ReadTextBox(WW8_DPHEAD const * pHd, SfxAllItemSet &rSet)
1222{
1223 bool bDummy;
1224 WW8_DP_TXTBOX aTextB;
1225
1226 if( !ReadGrafStart( static_cast<void*>(&aTextB), sizeof( aTextB ), pHd, rSet ) )
1227 return nullptr;
1228
1229 Point aP0( static_cast<sal_Int16>(SVBT16ToUInt16( pHd->xa )) + m_nDrawXOfs2,
1230 static_cast<sal_Int16>(SVBT16ToUInt16( pHd->ya )) + m_nDrawYOfs2 );
1231 Point aP1( aP0 );
1232 aP1.AdjustX(static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dxa )) );
1233 aP1.AdjustY(static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dya )) );
1234
1235 SdrRectObj* pObj = new SdrRectObj(
1236 *m_pDrawModel,
1237 OBJ_TEXT,
1238 tools::Rectangle(aP0, aP1));
1239
1240 pObj->NbcSetSnapRect(tools::Rectangle(aP0, aP1));
1241 Size aSize( static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dxa )) ,
1242 static_cast<sal_Int16>(SVBT16ToUInt16( pHd->dya )) );
1243
1244 long nStartCpFly,nEndCpFly;
1245 bool bContainsGraphics;
1246 InsertTxbxText(pObj, &aSize, 0, 0, 0, nullptr, false,
1247 bDummy,nullptr,&nStartCpFly,&nEndCpFly,&bContainsGraphics);
1248
1249 SetStdAttr( rSet, aTextB.aLnt, aTextB.aShd );
1250 SetFill( rSet, aTextB.aFill );
1251
1252 rSet.Put( SdrTextFitToSizeTypeItem( drawing::TextFitToSizeType_NONE ) );
1253 rSet.Put( makeSdrTextAutoGrowWidthItem(false));
1254 rSet.Put( makeSdrTextAutoGrowHeightItem(false));
1255 rSet.Put( makeSdrTextLeftDistItem( MIN_BORDER_DIST28*2 ) );
1256 rSet.Put( makeSdrTextRightDistItem( MIN_BORDER_DIST28*2 ) );
1257 rSet.Put( makeSdrTextUpperDistItem( MIN_BORDER_DIST28 ) );
1258 rSet.Put( makeSdrTextLowerDistItem( MIN_BORDER_DIST28 ) );
1259
1260 return pObj;
1261}
1262
1263SdrObject* SwWW8ImplReader::ReadCaptionBox(WW8_DPHEAD const * pHd, SfxAllItemSet &rSet)
1264{
1265 static const SdrCaptionType aCaptA[] = { SdrCaptionType::Type1, SdrCaptionType::Type2,
1266 SdrCaptionType::Type3, SdrCaptionType::Type4 };
1267
1268 WW8_DP_CALLOUT_TXTBOX aCallB;
1269
1270 if( !ReadGrafStart( static_cast<void*>(&aCallB), sizeof( aCallB ), pHd, rSet ) )
1271 return nullptr;
1272
1273 sal_uInt16 nCount = SVBT16ToUInt16( aCallB.dpPolyLine.aBits1 ) >> 1 & 0x7fff;
1274 if (nCount < 1)
1275 {
1276 SAL_WARN("sw.ww8", "Short CaptionBox header")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Short CaptionBox header"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1276" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Short CaptionBox header"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"Short CaptionBox header"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1276" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Short CaptionBox header") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1276" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Short CaptionBox header"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"Short CaptionBox header"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1276" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1277 return nullptr;
1278 }
1279
1280 std::unique_ptr<SVBT16[]> xP(new SVBT16[nCount * 2]);
1281
1282 bool bCouldRead = checkRead(*m_pStrm, xP.get(), nCount * 4); // read points
1283 if (!bCouldRead)
1284 {
1285 SAL_WARN("sw.ww8", "Short CaptionBox header")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Short CaptionBox header"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1285" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Short CaptionBox header"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"Short CaptionBox header"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1285" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Short CaptionBox header") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1285" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Short CaptionBox header"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"Short CaptionBox header"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1285" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1286 return nullptr;
1287 }
1288
1289 sal_uInt8 nTyp = static_cast<sal_uInt8>(nCount) - 1;
1290 if( nTyp == 1 && SVBT16ToUInt16( xP[0] ) == SVBT16ToUInt16( xP[2] ) )
1291 nTyp = 0;
1292
1293 Point aP0( static_cast<sal_Int16>(SVBT16ToUInt16( pHd->xa )) +
1294 static_cast<sal_Int16>(SVBT16ToUInt16( aCallB.dpheadTxbx.xa )) + m_nDrawXOfs2,
1295 static_cast<sal_Int16>(SVBT16ToUInt16( pHd->ya ))
1296 + static_cast<sal_Int16>(SVBT16ToUInt16( aCallB.dpheadTxbx.ya )) + m_nDrawYOfs2 );
1297 Point aP1( aP0 );
1298 aP1.AdjustX(static_cast<sal_Int16>(SVBT16ToUInt16( aCallB.dpheadTxbx.dxa )) );
1299 aP1.AdjustY(static_cast<sal_Int16>(SVBT16ToUInt16( aCallB.dpheadTxbx.dya )) );
1300 Point aP2( static_cast<sal_Int16>(SVBT16ToUInt16( pHd->xa ))
1301 + static_cast<sal_Int16>(SVBT16ToUInt16( aCallB.dpheadPolyLine.xa ))
1302 + m_nDrawXOfs2 + static_cast<sal_Int16>(SVBT16ToUInt16( xP[0] )),
1303 static_cast<sal_Int16>(SVBT16ToUInt16( pHd->ya ))
1304 + static_cast<sal_Int16>(SVBT16ToUInt16( aCallB.dpheadPolyLine.ya ))
1305 + m_nDrawYOfs2 + static_cast<sal_Int16>(SVBT16ToUInt16( xP[1] )) );
1306 xP.reset();
1307
1308 SdrCaptionObj* pObj = new SdrCaptionObj(
1309 *m_pDrawModel,
1310 tools::Rectangle(aP0, aP1),
1311 aP2);
1312
1313 pObj->NbcSetSnapRect(tools::Rectangle(aP0, aP1));
1314 Size aSize( static_cast<sal_Int16>(SVBT16ToUInt16( aCallB.dpheadTxbx.dxa )),
1315 static_cast<sal_Int16>(SVBT16ToUInt16( aCallB.dpheadTxbx.dya )) );
1316 bool bEraseThisObject;
1317
1318 InsertTxbxText(pObj, &aSize, 0, 0, 0, nullptr, false, bEraseThisObject );
1319
1320 if( SVBT16ToUInt16( aCallB.dptxbx.aLnt.lnps ) != 5 ) // Is border visible ?
1321 SetStdAttr( rSet, aCallB.dptxbx.aLnt, aCallB.dptxbx.aShd );
1322 else // no -> take lines
1323 SetStdAttr( rSet, aCallB.dpPolyLine.aLnt, aCallB.dptxbx.aShd );
1324 SetFill( rSet, aCallB.dptxbx.aFill );
1325 rSet.Put(SdrCaptionTypeItem(aCaptA[nTyp % SAL_N_ELEMENTS(aCaptA)(sizeof(sal_n_array_size(aCaptA)))]));
1326
1327 return pObj;
1328}
1329
1330SdrObject *SwWW8ImplReader::ReadGroup(WW8_DPHEAD const * pHd, SfxAllItemSet &rSet)
1331{
1332 sal_Int16 nGrouped;
1333
1334 if( !ReadGrafStart( static_cast<void*>(&nGrouped), sizeof( nGrouped ), pHd, rSet ) )
1335 return nullptr;
1336
1337#ifdef OSL_BIGENDIAN
1338 nGrouped = (sal_Int16)OSL_SWAPWORD( nGrouped )((sal_uInt16)((sal_uInt16)((((sal_uInt8)(((sal_uInt16)(nGrouped
) >> 8) & 0xFF))) & 0xFF) | (((sal_uInt16)(((sal_uInt8
)((sal_uInt16)(nGrouped) & 0xFF))) & 0xFF) << 8
)))
;
1339#endif
1340
1341 m_nDrawXOfs = m_nDrawXOfs + static_cast<sal_Int16>(SVBT16ToUInt16( pHd->xa ));
1342 m_nDrawYOfs = m_nDrawYOfs + static_cast<sal_Int16>(SVBT16ToUInt16( pHd->ya ));
1343
1344 SdrObject* pObj = new SdrObjGroup(*m_pDrawModel);
1345
1346 short nLeft = static_cast<sal_Int16>(SVBT16ToUInt16( pHd->cb )) - sizeof( WW8_DPHEAD );
1347 for (int i = 0; i < nGrouped && nLeft >= static_cast<short>(sizeof(WW8_DPHEAD)); ++i)
1348 {
1349 SfxAllItemSet aSet(m_pDrawModel->GetItemPool());
1350 if (SdrObject *pObject = ReadGrafPrimitive(nLeft, aSet))
1351 {
1352 // first add and then set ItemSet
1353 SdrObjList *pSubGroup = pObj->GetSubList();
1354 OSL_ENSURE(pSubGroup, "Why no sublist available?")do { if (true && (!(pSubGroup))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1354" ": "), "%s", "Why no sublist available?"); } } while
(false)
;
1355 if (pSubGroup)
1356 pSubGroup->InsertObject(pObject, 0);
1357 pObject->SetMergedItemSetAndBroadcast(aSet);
1358 }
1359 }
1360
1361 m_nDrawXOfs = m_nDrawXOfs - static_cast<sal_Int16>(SVBT16ToUInt16( pHd->xa ));
1362 m_nDrawYOfs = m_nDrawYOfs - static_cast<sal_Int16>(SVBT16ToUInt16( pHd->ya ));
1363
1364 return pObj;
1365}
1366
1367SdrObject* SwWW8ImplReader::ReadGrafPrimitive(short& rLeft, SfxAllItemSet &rSet)
1368{
1369 // This whole archaic word 6 graphic import can probably be refactored
1370 // into an object hierarchy with a little effort.
1371 SdrObject *pRet=nullptr;
1372 WW8_DPHEAD aHd; // Read Draw-Primitive-Header
1373 bool bCouldRead = checkRead(*m_pStrm, &aHd, sizeof(WW8_DPHEAD)) &&
1374 SVBT16ToUInt16(aHd.cb) >= sizeof(WW8_DPHEAD);
1375 OSL_ENSURE(bCouldRead, "Graphic Primitive header short read" )do { if (true && (!(bCouldRead))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1375" ": "), "%s", "Graphic Primitive header short read"
); } } while (false)
;
1376 if (!bCouldRead)
1377 {
1378 rLeft=0;
1379 return pRet;
1380 }
1381
1382 if( rLeft >= SVBT16ToUInt16(aHd.cb) ) // precautions
1383 {
1384 rSet.Put(SwFormatSurround(css::text::WrapTextMode_THROUGH));
1385 switch (SVBT16ToUInt16(aHd.dpk) & 0xff )
1386 {
1387 case 0:
1388 pRet = ReadGroup(&aHd, rSet);
1389 break;
1390 case 1:
1391 pRet = ReadLine(&aHd, rSet);
1392 break;
1393 case 2:
1394 pRet = ReadTextBox(&aHd, rSet);
1395 break;
1396 case 3:
1397 pRet = ReadRect(&aHd, rSet);
1398 break;
1399 case 4:
1400 pRet = ReadEllipse(&aHd, rSet);
1401 break;
1402 case 5:
1403 pRet = ReadArc(&aHd, rSet);
1404 break;
1405 case 6:
1406 pRet = ReadPolyLine(&aHd, rSet);
1407 break;
1408 case 7:
1409 pRet = ReadCaptionBox(&aHd, rSet);
1410 break;
1411 default: // unknown
1412 m_pStrm->SeekRel(SVBT16ToUInt16(aHd.cb) - sizeof(WW8_DPHEAD));
1413 break;
1414 }
1415 }
1416 else
1417 {
1418 OSL_ENSURE( false, "+Grafik-Overlap" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1418" ": "), "%s", "+Grafik-Overlap"); } } while (false
)
;
1419 }
1420 rLeft = rLeft - SVBT16ToUInt16( aHd.cb );
1421 return pRet;
1422}
1423
1424void SwWW8ImplReader::ReadGrafLayer1( WW8PLCFspecial* pPF, long nGrafAnchorCp )
1425{
1426 pPF->SeekPos( nGrafAnchorCp );
1427 WW8_FC nStartFc;
1428 void* pF0;
1429 if( !pPF->Get( nStartFc, pF0 ) )
1430 {
1431 OSL_ENSURE( false, "+Where is the graphic (2) ?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1431" ": "), "%s", "+Where is the graphic (2) ?"); } } while
(false)
;
1432 return;
1433 }
1434 WW8_FDOA* pF = static_cast<WW8_FDOA*>(pF0);
1435 if( !SVBT32ToUInt32( pF->fc ) )
1436 {
1437 OSL_ENSURE( false, "+Where is the graphic (3) ?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1437" ": "), "%s", "+Where is the graphic (3) ?"); } } while
(false)
;
1438 return;
1439 }
1440
1441 bool bCouldSeek = checkSeek(*m_pStrm, SVBT32ToUInt32(pF->fc));
1442 OSL_ENSURE(bCouldSeek, "Invalid graphic offset")do { if (true && (!(bCouldSeek))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1442" ": "), "%s", "Invalid graphic offset"); } } while
(false)
;
1443 if (!bCouldSeek)
1444 return;
1445
1446 // read Draw-Header
1447 WW8_DO aDo;
1448 bool bCouldRead = checkRead(*m_pStrm, &aDo, sizeof(WW8_DO));
1449 OSL_ENSURE(bCouldRead, "Short graphic header")do { if (true && (!(bCouldRead))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1449" ": "), "%s", "Short graphic header"); } } while (
false)
;
1450 if (!bCouldRead)
1451 return;
1452
1453 short nLeft = SVBT16ToUInt16( aDo.cb ) - sizeof( WW8_DO );
1454 while (nLeft > static_cast<short>(sizeof(WW8_DPHEAD)))
1455 {
1456 SfxAllItemSet aSet( m_pDrawModel->GetItemPool() );
1457 if (SdrObject *pObject = ReadGrafPrimitive(nLeft, aSet))
1458 {
1459 m_xWWZOrder->InsertDrawingObject(pObject, SVBT16ToUInt16(aDo.dhgt));
1460
1461 tools::Rectangle aRect(pObject->GetSnapRect());
1462
1463 const sal_uInt32 nCntRelTo = 3;
1464
1465 // Adjustment is horizontally relative to...
1466 static const sal_Int16 aHoriRelOriTab[nCntRelTo] =
1467 {
1468 text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
1469 text::RelOrientation::PAGE_FRAME, // 1 is page margin
1470 text::RelOrientation::FRAME, // 2 is relative to paragraph
1471 };
1472
1473 // Adjustment is vertically relative to...
1474 static const sal_Int16 aVertRelOriTab[nCntRelTo] =
1475 {
1476 text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
1477 text::RelOrientation::PAGE_FRAME, // 1 is page margin
1478 text::RelOrientation::FRAME, // 2 is relative to paragraph
1479 };
1480
1481 const int nXAlign = aDo.bx < nCntRelTo ? aDo.bx : 0;
1482 const int nYAlign = aDo.by < nCntRelTo ? aDo.by : 0;
1483
1484 aSet.Put(SwFormatHoriOrient(aRect.Left(), text::HoriOrientation::NONE,
1485 aHoriRelOriTab[ nXAlign ]));
1486 aSet.Put(SwFormatVertOrient(aRect.Top(), text::VertOrientation::NONE,
1487 aVertRelOriTab[ nYAlign ]));
1488
1489 SwFrameFormat *pFrame = m_rDoc.getIDocumentContentOperations().InsertDrawObj( *m_pPaM, *pObject, aSet );
1490 pObject->SetMergedItemSet(aSet);
1491
1492 if (SwDrawFrameFormat *pDrawFrame = dynamic_cast<SwDrawFrameFormat*>(pFrame))
1493 {
1494 pDrawFrame->PosAttrSet();
1495 }
1496
1497 AddAutoAnchor(pFrame);
1498 }
1499 }
1500}
1501
1502sal_Int32 SwMSDffManager::GetEscherLineMatch(MSO_LineStyle eStyle,
1503 MSO_SPT eShapeType, sal_Int32 &rThick)
1504{
1505 sal_Int32 nOutsideThick = 0;
1506 /*
1507 Note: In contrast to the regular WinWord table and frame border width,
1508 where the overall border width has to be calculated from the width of *one*
1509 line, the data from ESCHER already contains the overall width [twips]!
1510
1511 The WinWord default is 15 tw. We take for this our 20 tw line.
1512 (0.75 pt and 1.0 pt looking more similar on hardcopy than 0.75 pt and our
1513 0.05 pt hairline.) The hairline we only set by WinWord width up to max.
1514 0.5 pt.
1515 */
1516 switch( eStyle )
1517 {
1518 case mso_lineTriple:
1519 case mso_lineSimple:
1520 nOutsideThick = eShapeType != mso_sptTextBox ? rThick : rThick/2;
1521 break;
1522 case mso_lineDouble:
1523 if (eShapeType == mso_sptTextBox)
1524 {
1525 nOutsideThick = rThick/6;
1526 rThick = rThick*2/3;
1527 }
1528 else
1529 nOutsideThick = rThick*2/3;
1530 break;
1531 case mso_lineThickThin:
1532 if (eShapeType == mso_sptTextBox)
1533 {
1534 nOutsideThick = rThick*3/10;
1535 rThick = rThick*4/5;
1536 }
1537 else
1538 nOutsideThick = rThick*4/5;
1539 break;
1540 case mso_lineThinThick:
1541 {
1542 if (eShapeType == mso_sptTextBox)
1543 {
1544 nOutsideThick = rThick/10;
1545 rThick = rThick*3/5;
1546 }
1547 else
1548 nOutsideThick = rThick*3/5;
1549 }
1550 break;
1551 default:
1552 break;
1553 }
1554 return nOutsideThick;
1555}
1556
1557// Returns the thickness of the line outside the frame, the logic of
1558// words positioning of borders around floating objects is that of a
1559// disturbed mind.
1560sal_Int32 SwWW8ImplReader::MatchSdrBoxIntoFlyBoxItem(const Color& rLineColor,
1561 MSO_LineStyle eLineStyle, MSO_LineDashing eDashing, MSO_SPT eShapeType, sal_Int32 &rLineThick,
1562 SvxBoxItem& rBox )
1563{
1564 sal_Int32 nOutsideThick = 0;
1565 if( !rLineThick )
1566 return nOutsideThick;
1567
1568 SvxBorderLineStyle nIdx = SvxBorderLineStyle::NONE;
1569
1570 sal_Int32 nLineThick=rLineThick;
1571 nOutsideThick = SwMSDffManager::GetEscherLineMatch(eLineStyle,
1572 eShapeType, rLineThick);
1573
1574 /*
1575 Note: In contrast to the regular WinWord table and frame border width,
1576 where the overall border width has to be calculated from the width of *one*
1577 line, the data from ESCHER already contains the overall width [twips]!
1578
1579 The WinWord default is 15 tw. We take for this our 20 tw line.
1580 (0.75 pt and 1.0 pt looking more similar on hardcopy than 0.75 pt and our
1581 0.05 pt hairline.) The hairline we only set by WinWord width up to max.
1582 0.5 pt.
1583 */
1584 switch( +eLineStyle )
1585 {
1586 // first the single lines
1587 case mso_lineSimple:
1588 nIdx = SvxBorderLineStyle::SOLID;
1589 break;
1590 // second the double lines
1591 case mso_lineDouble:
1592 nIdx = SvxBorderLineStyle::DOUBLE;
1593 break;
1594 case mso_lineThickThin:
1595 nIdx = SvxBorderLineStyle::THICKTHIN_SMALLGAP;
1596 break;
1597 case mso_lineThinThick:
1598 nIdx = SvxBorderLineStyle::THINTHICK_SMALLGAP;
1599 break;
1600 // We have no triple border, use double instead.
1601 case mso_lineTriple:
1602 nIdx = SvxBorderLineStyle::DOUBLE;
1603 break;
1604 // no line style is set
1605 case MSO_LineStyle(USHRT_MAX(32767 *2 +1)):
1606 break;
1607 // erroneously not implemented line style is set
1608 default:
1609 OSL_ENSURE(false, "eLineStyle is not (yet) implemented!")do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "1609" ": "), "%s", "eLineStyle is not (yet) implemented!"
); } } while (false)
;
1610 break;
1611 }
1612
1613 switch( eDashing )
1614 {
1615 case mso_lineDashGEL:
1616 nIdx = SvxBorderLineStyle::DASHED;
1617 break;
1618 case mso_lineDotGEL:
1619 nIdx = SvxBorderLineStyle::DOTTED;
1620 break;
1621 default:
1622 break;
1623 }
1624
1625 if (SvxBorderLineStyle::NONE != nIdx)
1626 {
1627 SvxBorderLine aLine;
1628 aLine.SetColor( rLineColor );
1629
1630 aLine.SetWidth( nLineThick ); // No conversion here, nLineThick is already in twips
1631 aLine.SetBorderLineStyle(nIdx);
1632
1633 for(SvxBoxItemLine nLine : o3tl::enumrange<SvxBoxItemLine>())
1634 {
1635 // aLine is cloned by SetLine
1636 rBox.SetLine(&aLine, nLine);
1637 }
1638 }
1639
1640 return nOutsideThick;
1641}
1642
1643#define WW8ITEMVALUE(ItemSet,Id,Cast)ItemSet.GetItem<Cast>(Id)->GetValue() ItemSet.GetItem<Cast>(Id)->GetValue()
1644
1645void SwWW8ImplReader::MatchSdrItemsIntoFlySet( SdrObject const * pSdrObj,
1646 SfxItemSet& rFlySet, MSO_LineStyle eLineStyle, MSO_LineDashing eDashing, MSO_SPT eShapeType,
1647 tools::Rectangle& rInnerDist )
1648{
1649 /*
1650 attributes to be set on the frame
1651 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1652 SwFormatFrameSize if not set, set here
1653 SvxLRSpaceItem set here
1654 SvxULSpaceItem set here
1655 SvxOpaqueItem (Currently not possible for frames! khz 10.2.1999)
1656 SwFormatSurround already set
1657 SwFormatVertOrient already set
1658 SwFormatHoriOrient already set
1659 SwFormatAnchor already set
1660 SvxBoxItem set here
1661 SvxBrushItem set here
1662 SvxShadowItem set here
1663 */
1664
1665 // 1. GraphicObject of documents?
1666 GrafikCtor();
1667
1668 const SfxItemSet& rOldSet = pSdrObj->GetMergedItemSet();
1669
1670 // some Items can be taken over directly
1671 static sal_uInt16 const aDirectMatch[]
1672 {
1673 RES_LR_SPACE, // outer spacing left/right: SvxLRSpaceItem
1674 RES_UL_SPACE // outer spacing top/bottom: SvxULSpaceItem
1675 };
1676 const SfxPoolItem* pPoolItem;
1677 for(sal_uInt16 i : aDirectMatch)
1678 if( SfxItemState::SET == rOldSet.GetItemState(i, false, &pPoolItem) )
1679 {
1680 rFlySet.Put( *pPoolItem );
1681 }
1682
1683 // take new XATTR items directly. Skip old RES_BACKGROUND if new FILLSTYLE taken.
1684 bool bSkipResBackground = false;
1685 SfxItemPool* pPool = rFlySet.GetPool();
1686 if ( pPool )
1687 {
1688 for ( sal_uInt16 i = XATTR_START; i < XATTR_END; ++i )
1689 {
1690 // Not all Fly types support XATTRs - skip unsupported attributes
1691 SfxItemPool* pAttrPool = pPool->GetMasterPool();
1692 while ( pAttrPool && !pAttrPool->IsInRange(i) )
1693 pAttrPool = pAttrPool->GetSecondaryPool();
1694 if ( !pAttrPool )
1695 continue;
1696
1697 if ( SfxItemState::SET == rOldSet.GetItemState(i, false, &pPoolItem) )
1698 {
1699 rFlySet.Put( *pPoolItem );
1700 if ( i == XATTR_FILLSTYLE )
1701 {
1702 const drawing::FillStyle eFill = static_cast<const XFillStyleItem*>(pPoolItem)->GetValue();
1703 // Transparency forced in certain situations when fillstyle is none - use old logic for that case still
1704 // which is especially needed for export purposes (tdf112618).
1705 if ( eFill != drawing::FillStyle_NONE )
1706 bSkipResBackground = true;
1707 }
1708 }
1709 }
1710 }
1711
1712 // now calculate the borders and build the box: The unit is needed for the
1713 // frame SIZE!
1714 SvxBoxItem aBox(sw::util::ItemGet<SvxBoxItem>(rFlySet, RES_BOX));
1715 // dashed or solid becomes solid
1716 // WW-default: 0.75 pt = 15 twips
1717 sal_Int32 nLineThick = 15, nOutside=0;
1718
1719 // check if LineStyle is *really* set!
1720 const SfxPoolItem* pItem;
1721
1722 SfxItemState eState = rOldSet.GetItemState(XATTR_LINESTYLE,true,&pItem);
1723 if( eState == SfxItemState::SET )
1724 {
1725 // Now, that we know there is a line style we will make use the
1726 // parameter given to us when calling the method... :-)
1727 const Color aLineColor = rOldSet.Get(XATTR_LINECOLOR).GetColorValue();
1728 nLineThick = WW8ITEMVALUE(rOldSet, XATTR_LINEWIDTH, XLineWidthItem)rOldSet.GetItem<XLineWidthItem>(XATTR_LINEWIDTH)->GetValue
()
;
1729
1730 if( !nLineThick )
1731 nLineThick = 1; // for Writer, zero is "no border", so set a minimal value
1732
1733 nOutside = MatchSdrBoxIntoFlyBoxItem(aLineColor, eLineStyle,
1734 eDashing, eShapeType, nLineThick, aBox);
1735 }
1736
1737 rInnerDist.AdjustLeft(nLineThick );
1738 rInnerDist.AdjustTop(nLineThick );
1739 rInnerDist.AdjustRight(nLineThick );
1740 rInnerDist.AdjustBottom(nLineThick );
1741
1742 rInnerDist.AdjustLeft( -(aBox.CalcLineWidth( SvxBoxItemLine::LEFT )) );
1743 rInnerDist.AdjustTop( -(aBox.CalcLineWidth( SvxBoxItemLine::TOP )) );
1744 rInnerDist.AdjustRight( -(aBox.CalcLineWidth( SvxBoxItemLine::RIGHT )) );
1745 rInnerDist.AdjustBottom( -(aBox.CalcLineWidth( SvxBoxItemLine::BOTTOM )) );
1746
1747 // set distances from box's border to text contained within the box
1748 if( 0 < rInnerDist.Left() )
1749 aBox.SetDistance( static_cast<sal_uInt16>(rInnerDist.Left()), SvxBoxItemLine::LEFT );
1750 if( 0 < rInnerDist.Top() )
1751 aBox.SetDistance( static_cast<sal_uInt16>(rInnerDist.Top()), SvxBoxItemLine::TOP );
1752 if( 0 < rInnerDist.Right() )
1753 aBox.SetDistance( static_cast<sal_uInt16>(rInnerDist.Right()), SvxBoxItemLine::RIGHT );
1754 if( 0 < rInnerDist.Bottom() )
1755 aBox.SetDistance( static_cast<sal_uInt16>(rInnerDist.Bottom()), SvxBoxItemLine::BOTTOM );
1756
1757 bool bFixSize = !(WW8ITEMVALUE(rOldSet, SDRATTR_TEXT_AUTOGROWHEIGHT,rOldSet.GetItem<SdrOnOffItem>(SDRATTR_TEXT_AUTOGROWHEIGHT
)->GetValue()
1758 SdrOnOffItem)rOldSet.GetItem<SdrOnOffItem>(SDRATTR_TEXT_AUTOGROWHEIGHT
)->GetValue()
);
1759
1760 // Size: SwFormatFrameSize
1761 if( SfxItemState::SET != rFlySet.GetItemState(RES_FRM_SIZE, false) )
1762 {
1763 const tools::Rectangle& rSnapRect = pSdrObj->GetSnapRect();
1764 // if necessary adapt width and position of the framework: The
1765 // recorded interior is to remain equally large despite thick edges.
1766 rFlySet.Put( SwFormatFrameSize(bFixSize ? SwFrameSize::Fixed : SwFrameSize::Variable,
1767 rSnapRect.GetWidth() + 2*nOutside,
1768 rSnapRect.GetHeight() + 2*nOutside) );
1769 }
1770 else // If a size is set, adjust it to consider border thickness
1771 {
1772 SwFormatFrameSize aSize = rFlySet.Get(RES_FRM_SIZE);
1773
1774 SwFormatFrameSize aNewSize(bFixSize ? SwFrameSize::Fixed : SwFrameSize::Variable,
1775 aSize.GetWidth() + 2*nOutside,
1776 aSize.GetHeight() + 2*nOutside);
1777 aNewSize.SetWidthSizeType(aSize.GetWidthSizeType());
1778 rFlySet.Put( aNewSize );
1779 }
1780
1781 // Sadly word puts escher borders outside the graphic, but orients the
1782 // graphic in relation to the top left inside the border. We don't
1783 if (nOutside)
1784 {
1785 SwFormatHoriOrient aHori = rFlySet.Get(RES_HORI_ORIENT);
1786 aHori.SetPos(MakeSafePositioningValue(aHori.GetPos()-nOutside));
1787 rFlySet.Put(aHori);
1788
1789 SwFormatVertOrient aVert = rFlySet.Get(RES_VERT_ORIENT);
1790 aVert.SetPos(aVert.GetPos()-nOutside);
1791 rFlySet.Put(aVert);
1792 }
1793
1794 // now set the border
1795 rFlySet.Put( aBox );
1796
1797 // shadow of the box: SvxShadowItem
1798 if( WW8ITEMVALUE(rOldSet, SDRATTR_SHADOW, SdrOnOffItem)rOldSet.GetItem<SdrOnOffItem>(SDRATTR_SHADOW)->GetValue
()
)
1799 {
1800 SvxShadowItem aShadow( RES_SHADOW );
1801
1802 const Color aShdColor = rOldSet.Get(SDRATTR_SHADOWCOLOR).GetColorValue();
1803 const sal_Int32 nShdDistX = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWXDIST,rOldSet.GetItem<SdrMetricItem>(SDRATTR_SHADOWXDIST)->
GetValue()
1804 SdrMetricItem)rOldSet.GetItem<SdrMetricItem>(SDRATTR_SHADOWXDIST)->
GetValue()
;
1805 const sal_Int32 nShdDistY = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWYDIST,rOldSet.GetItem<SdrMetricItem>(SDRATTR_SHADOWYDIST)->
GetValue()
1806 SdrMetricItem)rOldSet.GetItem<SdrMetricItem>(SDRATTR_SHADOWYDIST)->
GetValue()
;
1807
1808 aShadow.SetColor( aShdColor );
1809
1810 aShadow.SetWidth(writer_cast<sal_uInt16>((std::abs( nShdDistX) +
1811 std::abs( nShdDistY )) / 2 ));
1812
1813 SvxShadowLocation eShdPosi;
1814 if( 0 <= nShdDistX )
1815 {
1816 if( 0 <= nShdDistY )
1817 eShdPosi = SvxShadowLocation::BottomRight;
1818 else
1819 eShdPosi = SvxShadowLocation::TopRight;
1820 }
1821 else
1822 {
1823 if( 0 <= nShdDistY )
1824 eShdPosi = SvxShadowLocation::BottomLeft;
1825 else
1826 eShdPosi = SvxShadowLocation::TopLeft;
1827 }
1828 aShadow.SetLocation( eShdPosi );
1829
1830 rFlySet.Put( aShadow );
1831 }
1832 SvxBrushItem aBrushItem(COL_WHITE, RES_BACKGROUND);
1833 bool bBrushItemOk = false;
1834 sal_uInt8 nTrans = 0;
1835
1836 // Separate transparency
1837 eState = rOldSet.GetItemState(XATTR_FILLTRANSPARENCE, true, &pItem);
1838 if (!bSkipResBackground && eState == SfxItemState::SET)
1839 {
1840 sal_uInt16 nRes = WW8ITEMVALUE(rOldSet, XATTR_FILLTRANSPARENCE,rOldSet.GetItem<XFillTransparenceItem>(XATTR_FILLTRANSPARENCE
)->GetValue()
1841 XFillTransparenceItem)rOldSet.GetItem<XFillTransparenceItem>(XATTR_FILLTRANSPARENCE
)->GetValue()
;
1842 nTrans = sal_uInt8((nRes * 0xFE) / 100);
1843 aBrushItem.GetColor().SetTransparency(nTrans);
1844 bBrushItemOk = true;
1845 }
1846
1847 // Background: SvxBrushItem
1848 eState = rOldSet.GetItemState(XATTR_FILLSTYLE, true, &pItem);
1849 if (!bSkipResBackground && eState == SfxItemState::SET)
1850 {
1851 const drawing::FillStyle eFill = static_cast<const XFillStyleItem*>(pItem)->GetValue();
1852
1853 switch (eFill)
1854 {
1855 default:
1856 case drawing::FillStyle_NONE:
1857 // Writer graphics don't have it yet
1858 if (eShapeType != mso_sptPictureFrame)
1859 {
1860 aBrushItem.GetColor().SetTransparency(0xFE);
1861 bBrushItemOk = true;
1862 }
1863 break;
1864 case drawing::FillStyle_SOLID:
1865 case drawing::FillStyle_GRADIENT:
1866 {
1867 const Color aColor =
1868 rOldSet.Get(XATTR_FILLCOLOR).GetColorValue();
1869 aBrushItem.SetColor(aColor);
1870
1871 if (bBrushItemOk) // has trans
1872 aBrushItem.GetColor().SetTransparency(nTrans);
1873
1874 bBrushItemOk = true;
1875 }
1876 break;
1877 case drawing::FillStyle_HATCH:
1878 break;
1879 case drawing::FillStyle_BITMAP:
1880 {
1881 GraphicObject aGrfObj(rOldSet.Get(XATTR_FILLBITMAP).GetGraphicObject());
1882 const bool bTile(WW8ITEMVALUE(rOldSet, XATTR_FILLBMP_TILE, SfxBoolItem)rOldSet.GetItem<SfxBoolItem>(XATTR_FILLBMP_TILE)->GetValue
()
);
1883
1884 if(bBrushItemOk) // has trans
1885 {
1886 GraphicAttr aAttr(aGrfObj.GetAttr());
1887
1888 aAttr.SetTransparency(nTrans);
1889 aGrfObj.SetAttr(aAttr);
1890 }
1891
1892 aBrushItem.SetGraphicObject(aGrfObj);
1893 aBrushItem.SetGraphicPos(bTile ? GPOS_TILED : GPOS_AREA);
1894 bBrushItemOk = true;
1895 }
1896 break;
1897 }
1898 }
1899
1900 if (bBrushItemOk)
1901 rFlySet.Put(aBrushItem);
1902}
1903
1904void SwWW8ImplReader::AdjustLRWrapForWordMargins(
1905 const SvxMSDffImportRec &rRecord, SvxLRSpaceItem &rLR)
1906{
1907 sal_uInt32 nXRelTo = SvxMSDffImportRec::RELTO_DEFAULT;
1908 if ( rRecord.nXRelTo )
1909 {
1910 nXRelTo = *rRecord.nXRelTo;
1911 }
1912
1913 // Left adjustments - if horizontally aligned to left of
1914 // margin or column then remove the left wrapping
1915 if (rRecord.nXAlign == 1)
1916 {
1917 if ((nXRelTo == 0) || (nXRelTo == 2))
1918 rLR.SetLeft(sal_uInt16(0));
1919 }
1920
1921 // Right adjustments - if horizontally aligned to right of
1922 // margin or column then remove the right wrapping
1923 if (rRecord.nXAlign == 3)
1924 {
1925 if ((nXRelTo == 0) || (nXRelTo == 2))
1926 rLR.SetRight(sal_uInt16(0));
1927 }
1928
1929 // Inside margin, remove left wrapping
1930 if ((rRecord.nXAlign == 4) && (nXRelTo == 0))
1931 {
1932 rLR.SetLeft(sal_uInt16(0));
1933 }
1934
1935 // Outside margin, remove left wrapping
1936 if ((rRecord.nXAlign == 5) && (nXRelTo == 0))
1937 {
1938 rLR.SetRight(sal_uInt16(0));
1939 }
1940}
1941
1942void SwWW8ImplReader::AdjustULWrapForWordMargins(
1943 const SvxMSDffImportRec &rRecord, SvxULSpaceItem &rUL)
1944{
1945 sal_uInt32 nYRelTo = SvxMSDffImportRec::RELTO_DEFAULT;
1946 if ( rRecord.nYRelTo )
1947 {
1948 nYRelTo = *rRecord.nYRelTo;
1949 }
1950
1951 // Top adjustment - remove upper wrapping if aligned to page
1952 // printable area or to page
1953 if (rRecord.nYAlign == 1)
1954 {
1955 if ((nYRelTo == 0) || (nYRelTo == 1))
1956 rUL.SetUpper(sal_uInt16(0));
1957 }
1958
1959 // Bottom adjustment - remove bottom wrapping if aligned to page or
1960 // printable area or to page
1961 if (rRecord.nYAlign == 3)
1962 {
1963 if ((nYRelTo == 0) || (nYRelTo == 1))
1964 rUL.SetLower(sal_uInt16(0));
1965 }
1966
1967 // Remove top margin if aligned vertically inside margin
1968 if ((rRecord.nYAlign == 4) && (nYRelTo == 0))
1969 rUL.SetUpper(sal_uInt16(0));
1970}
1971
1972void SwWW8ImplReader::MapWrapIntoFlyFormat(SvxMSDffImportRec const * pRecord,
1973 SwFrameFormat* pFlyFormat)
1974{
1975 if (!pRecord || !pFlyFormat)
1976 return;
1977
1978 if (pRecord->nDxWrapDistLeft || pRecord->nDxWrapDistRight)
1979 {
1980 SvxLRSpaceItem aLR(writer_cast<sal_uInt16>(pRecord->nDxWrapDistLeft),
1981 writer_cast<sal_uInt16>(pRecord->nDxWrapDistRight), 0, 0, RES_LR_SPACE);
1982 AdjustLRWrapForWordMargins(*pRecord, aLR);
1983 pFlyFormat->SetFormatAttr(aLR);
1984 }
1985 if (pRecord->nDyWrapDistTop || pRecord->nDyWrapDistBottom)
1986 {
1987 SvxULSpaceItem aUL(writer_cast<sal_uInt16>(pRecord->nDyWrapDistTop),
1988 writer_cast<sal_uInt16>(pRecord->nDyWrapDistBottom), RES_UL_SPACE);
1989 AdjustULWrapForWordMargins(*pRecord, aUL);
1990 pFlyFormat->SetFormatAttr(aUL);
1991 }
1992
1993 // If we are contoured and have a custom polygon...
1994 if (pRecord->pWrapPolygon && pFlyFormat->GetSurround().IsContour())
1995 {
1996 if (SwNoTextNode *pNd = GetNoTextNodeFromSwFrameFormat(*pFlyFormat))
1997 {
1998
1999 /*
2000 Gather round children and hear of a tale that will raise the
2001 hairs on the back of your neck this dark halloween night.
2002
2003 There is a polygon in word that describes the wrapping around
2004 the graphic.
2005
2006 Here are some sample values for the simplest case of a square
2007 around some solid coloured graphics
2008
2009 X Y Pixel size of graphic
2010 TopLeft -54 21600 400x400
2011 Bottom Right 0 21546
2012
2013 TopLeft -108 21600 200x200
2014 Bottom Right 0 21492
2015
2016 TopLeft -216 21600 100x100
2017 Bottom Right 0 21384
2018
2019 TopLeft -432 21600 50x50
2020 Bottom Right 0 21168
2021
2022 TopLeft -76 21600 283x212
2023 Bottom Right 0 21498
2024
2025 So given that the size of the values remains pretty much the
2026 same despite the size of the graphic, we can tell that the
2027 polygon is measured in units that are independent of the
2028 graphic. But why does the left corner move a different value
2029 to the left each time, and why does the bottom move upwards
2030 each time, when the right and top remain at the same value ?
2031
2032 I have no idea, but clearly once we calculate the values out
2033 we see that the left margin is always a fixed realworld
2034 distance from the true left and the polygon bottom is the same
2035 fixed value from the bottom. i.e. 15twips.
2036
2037 So here we take our word provided polygon, shift it to the
2038 right by 15twips and rescale it widthwise to shrink the width
2039 a little to fit the now moved right margin back to where it
2040 was, and stretch the height a little to make the bottom move
2041 down the missing 15twips then we get a polygon that matches
2042 what I actually see in word
2043 */
2044
2045 tools::PolyPolygon aPoly(*pRecord->pWrapPolygon);
2046 const Size &rSize = pNd->GetTwipSize();
2047 /*
2048 Move to the left by 15twips, and rescale to
2049 a) shrink right bound back to orig position
2050 b) stretch bottom bound to where I think it should have been
2051 in the first place
2052 */
2053 Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
2054 aMoveHack *= Fraction(15, 1);
2055 long nMove(aMoveHack);
2056 aPoly.Move(nMove, 0);
2057
2058 Fraction aHackX(ww::nWrap100Percent, ww::nWrap100Percent + nMove);
2059 Fraction aHackY(ww::nWrap100Percent, ww::nWrap100Percent - nMove);
2060 aPoly.Scale(double(aHackX), double(aHackY));
2061
2062 // Turn polygon back into units that match the graphic's
2063 const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
2064 Fraction aMapPolyX(rOrigSize.Width(), ww::nWrap100Percent);
2065 Fraction aMapPolyY(rOrigSize.Height(), ww::nWrap100Percent);
2066 aPoly.Scale(double(aMapPolyX), double(aMapPolyY));
2067
2068 // #i47277# - contour is already in unit of the
2069 // graphic preferred unit. Thus, call method <SetContour(..)>
2070 pNd->SetContour(&aPoly);
2071 }
2072 }
2073 else if (pFlyFormat->GetSurround().IsContour())
2074 {
2075 // Contour is enabled, but no polygon is set: disable contour, because Word does not
2076 // Writer-style auto-contour in that case.
2077 SwFormatSurround aSurround(pFlyFormat->GetSurround());
2078 aSurround.SetContour(false);
2079 pFlyFormat->SetFormatAttr(aSurround);
2080 }
2081}
2082
2083static sal_Int32 lcl_ConvertCrop(sal_uInt32 const nCrop, sal_Int32 const nSize)
2084{
2085 // cast to sal_Int32 to handle negative crop properly
2086 sal_Int32 const nIntegral(static_cast<sal_Int32>(nCrop) >> 16);
2087 // fdo#77454: heuristic to detect mangled values written by old OOo/LO
2088 if (abs(nIntegral) >= 50) // FIXME: what's a good cut-off?
2089 {
2090 SAL_INFO("sw.ww8", "ignoring suspiciously large crop: " << nIntegral)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ignoring suspiciously large crop: "
<< nIntegral) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2090" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ignoring suspiciously large crop: "
<< nIntegral), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "ignoring suspiciously large crop: "
<< nIntegral; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2090" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ignoring suspiciously large crop: " << nIntegral
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("sw.ww8"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2090" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ignoring suspiciously large crop: "
<< nIntegral), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "ignoring suspiciously large crop: "
<< nIntegral; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2090" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2091 return 0;
2092 }
2093 return (nIntegral * nSize) + (((nCrop & 0xffff) * nSize) >> 16);
2094}
2095
2096void
2097SwWW8ImplReader::SetAttributesAtGrfNode(SvxMSDffImportRec const*const pRecord,
2098 SwFrameFormat const *pFlyFormat, WW8_FSPA const *pF )
2099{
2100 const SwNodeIndex* pIdx = pFlyFormat->GetContent(false).GetContentIdx();
2101 SwGrfNode *const pGrfNd(
2102 pIdx ? m_rDoc.GetNodes()[pIdx->GetIndex() + 1]->GetGrfNode() : nullptr);
2103 if (!pGrfNd)
2104 return;
2105
2106 Size aSz(pGrfNd->GetTwipSize());
2107 // use type <sal_uInt64> instead of sal_uLong to get correct results
2108 // in the following calculations.
2109 sal_uInt64 nHeight = aSz.Height();
2110 sal_uInt64 nWidth = aSz.Width();
2111 if (!nWidth && pF)
2112 nWidth = o3tl::saturating_sub(pF->nXaRight, pF->nXaLeft);
2113 else if (!nHeight && pF)
2114 nHeight = o3tl::saturating_sub(pF->nYaBottom, pF->nYaTop);
2115
2116 if( pRecord->nCropFromTop || pRecord->nCropFromBottom ||
2117 pRecord->nCropFromLeft || pRecord->nCropFromRight )
2118 {
2119 SwCropGrf aCrop; // Cropping is stored in 'fixed floats'
2120 // 16.16 (fraction times total
2121 if( pRecord->nCropFromTop ) // image width or height resp.)
2122 {
2123 aCrop.SetTop(lcl_ConvertCrop(pRecord->nCropFromTop, nHeight));
2124 }
2125 if( pRecord->nCropFromBottom )
2126 {
2127 aCrop.SetBottom(lcl_ConvertCrop(pRecord->nCropFromBottom, nHeight));
2128 }
2129 if( pRecord->nCropFromLeft )
2130 {
2131 aCrop.SetLeft(lcl_ConvertCrop(pRecord->nCropFromLeft, nWidth));
2132 }
2133 if( pRecord->nCropFromRight )
2134 {
2135 aCrop.SetRight(lcl_ConvertCrop(pRecord->nCropFromRight, nWidth));
2136 }
2137
2138 pGrfNd->SetAttr( aCrop );
2139 }
2140
2141 bool bFlipH(pRecord->nFlags & ShapeFlag::FlipH);
2142 bool bFlipV(pRecord->nFlags & ShapeFlag::FlipV);
2143 if ( bFlipH || bFlipV )
2144 {
2145 SwMirrorGrf aMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf();
2146 if( bFlipH )
2147 {
2148 if( bFlipV )
2149 aMirror.SetValue(MirrorGraph::Both);
2150 else
2151 aMirror.SetValue(MirrorGraph::Vertical);
2152 }
2153 else
2154 aMirror.SetValue(MirrorGraph::Horizontal);
2155
2156 pGrfNd->SetAttr( aMirror );
2157 }
2158
2159 if (!pRecord->pObj)
2160 return;
2161
2162 const SfxItemSet& rOldSet = pRecord->pObj->GetMergedItemSet();
2163 // contrast
2164 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFCONTRAST,rOldSet.GetItem<SdrGrafContrastItem>(SDRATTR_GRAFCONTRAST
)->GetValue()
2165 SdrGrafContrastItem)rOldSet.GetItem<SdrGrafContrastItem>(SDRATTR_GRAFCONTRAST
)->GetValue()
)
2166 {
2167 SwContrastGrf aContrast(
2168 WW8ITEMVALUE(rOldSet,rOldSet.GetItem<SdrGrafContrastItem>(SDRATTR_GRAFCONTRAST
)->GetValue()
2169 SDRATTR_GRAFCONTRAST, SdrGrafContrastItem)rOldSet.GetItem<SdrGrafContrastItem>(SDRATTR_GRAFCONTRAST
)->GetValue()
);
2170 pGrfNd->SetAttr( aContrast );
2171 }
2172
2173 // luminance
2174 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFLUMINANCE,rOldSet.GetItem<SdrGrafLuminanceItem>(SDRATTR_GRAFLUMINANCE
)->GetValue()
2175 SdrGrafLuminanceItem)rOldSet.GetItem<SdrGrafLuminanceItem>(SDRATTR_GRAFLUMINANCE
)->GetValue()
)
2176 {
2177 SwLuminanceGrf aLuminance(WW8ITEMVALUE(rOldSet,rOldSet.GetItem<SdrGrafLuminanceItem>(SDRATTR_GRAFLUMINANCE
)->GetValue()
2178 SDRATTR_GRAFLUMINANCE, SdrGrafLuminanceItem)rOldSet.GetItem<SdrGrafLuminanceItem>(SDRATTR_GRAFLUMINANCE
)->GetValue()
);
2179 pGrfNd->SetAttr( aLuminance );
2180 }
2181 // gamma
2182 if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA, SdrGrafGamma100Item)rOldSet.GetItem<SdrGrafGamma100Item>(SDRATTR_GRAFGAMMA)
->GetValue()
)
2183 {
2184 double fVal = WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA,rOldSet.GetItem<SdrGrafGamma100Item>(SDRATTR_GRAFGAMMA)
->GetValue()
2185 SdrGrafGamma100Item)rOldSet.GetItem<SdrGrafGamma100Item>(SDRATTR_GRAFGAMMA)
->GetValue()
;
2186 pGrfNd->SetAttr(SwGammaGrf(fVal/100.));
2187 }
2188
2189 // drawmode
2190 auto nGrafMode = rOldSet.GetItem<SdrGrafModeItem>(SDRATTR_GRAFMODE)->GetValue();
2191 if ( nGrafMode != GraphicDrawMode::Standard)
2192 {
2193 SwDrawModeGrf aDrawMode( nGrafMode );
2194 pGrfNd->SetAttr( aDrawMode );
2195 }
2196}
2197
2198SdrObject* SwWW8ImplReader::CreateContactObject(SwFrameFormat* pFlyFormat)
2199{
2200 if (pFlyFormat)
2201 {
2202 SdrObject* pNewObject = m_bNewDoc ? nullptr : pFlyFormat->FindRealSdrObject();
2203 if (!pNewObject)
2204 pNewObject = pFlyFormat->FindSdrObject();
2205 if (!pNewObject && dynamic_cast< const SwFlyFrameFormat *>( pFlyFormat ) != nullptr)
2206 {
2207 SwFlyDrawContact* pContactObject(static_cast<SwFlyFrameFormat*>(pFlyFormat)->GetOrCreateContact());
2208 pNewObject = pContactObject->GetMaster();
2209 }
2210 return pNewObject;
2211 }
2212 return nullptr;
2213}
2214
2215// Miserable miserable hack to fudge word's graphic layout in RTL mode to ours.
2216bool SwWW8ImplReader::MiserableRTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
2217 sal_Int16 eHoriOri, sal_Int16 eHoriRel)
2218{
2219 if (!IsRightToLeft())
2220 return false;
2221 return RTLGraphicsHack(rLeft, nWidth, eHoriOri, eHoriRel,
2222 m_aSectionManager.GetPageLeft(),
2223 m_aSectionManager.GetPageRight(),
2224 m_aSectionManager.GetPageWidth());
2225}
2226
2227RndStdIds SwWW8ImplReader::ProcessEscherAlign(SvxMSDffImportRec* pRecord,
2228 WW8_FSPA *pFSPA, SfxItemSet &rFlySet)
2229{
2230 OSL_ENSURE(pRecord || pFSPA, "give me something! to work with for anchoring")do { if (true && (!(pRecord || pFSPA))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2230" ": "), "%s", "give me something! to work with for anchoring"
); } } while (false)
;
2231 if (!pRecord && !pFSPA)
2232 return RndStdIds::FLY_AT_PAGE;
2233 bool bCurSectionVertical = m_aSectionManager.CurrentSectionIsVertical();
2234
2235 SvxMSDffImportRec aRecordFromFSPA;
2236 if (!pRecord)
2237 pRecord = &aRecordFromFSPA;
2238 if (!(pRecord->nXRelTo) && pFSPA)
2239 {
2240 pRecord->nXRelTo = sal_Int32(pFSPA->nbx);
2241 }
2242 if (!(pRecord->nYRelTo) && pFSPA)
2243 {
2244 pRecord->nYRelTo = sal_Int32(pFSPA->nby);
2245 }
2246
2247 // nXAlign - abs. Position, Left, Centered, Right, Inside, Outside
2248 // nYAlign - abs. Position, Top, Centered, Bottom, Inside, Outside
2249
2250 // nXRelTo - Page printable area, Page, Column, Character
2251 // nYRelTo - Page printable area, Page, Paragraph, Line
2252
2253 const sal_uInt32 nCntXAlign = 6;
2254 const sal_uInt32 nCntYAlign = 6;
2255
2256 const sal_uInt32 nCntRelTo = 4;
2257
2258 sal_uInt32 nXAlign = nCntXAlign > pRecord->nXAlign ? pRecord->nXAlign : 1;
2259 sal_uInt32 nYAlign = nCntYAlign > pRecord->nYAlign ? pRecord->nYAlign : 1;
2260
2261 if (pFSPA)
2262 {
2263 // #i52565# - try to handle special case for objects in tables regarding its X Rel
2264
2265 // if X and Y Rel values are on default take it as a hint, that they have not been set
2266 // by <SwMSDffManager::ProcessObj(..)>
2267 const bool bXYRelHaveDefaultValues = *pRecord->nXRelTo == 2 && *pRecord->nYRelTo == 2;
2268 if ( bXYRelHaveDefaultValues
2269 && m_nInTable > 0
2270 && !bCurSectionVertical )
2271 {
2272 if ( sal_uInt32(pFSPA->nby) != pRecord->nYRelTo )
2273 {
2274 pRecord->nYRelTo = sal_uInt32(pFSPA->nby);
2275 }
2276 }
2277 }
2278
2279 sal_uInt32 nXRelTo = (pRecord->nXRelTo && nCntRelTo > pRecord->nXRelTo) ? *pRecord->nXRelTo : 1;
2280 sal_uInt32 nYRelTo = (pRecord->nYRelTo && nCntRelTo > pRecord->nYRelTo) ? *pRecord->nYRelTo : 1;
2281
2282 RndStdIds eAnchor = IsInlineEscherHack() ? RndStdIds::FLY_AS_CHAR : RndStdIds::FLY_AT_CHAR; // #i43718#
2283
2284 SwFormatAnchor aAnchor( eAnchor );
2285 aAnchor.SetAnchor( m_pPaM->GetPoint() );
2286 rFlySet.Put( aAnchor );
2287
2288 if (pFSPA)
2289 {
2290 // #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 // #i36649#
2302 // - inside -> text::HoriOrientation::LEFT and outside -> text::HoriOrientation::RIGHT
2303 text::HoriOrientation::LEFT, // inside
2304 text::HoriOrientation::RIGHT // outside
2305 };
2306
2307 // generic vertical Adjustment
2308 static const sal_Int16 aVertOriTab[ nCntYAlign ] =
2309 {
2310 text::VertOrientation::NONE, // From Top position
2311 text::VertOrientation::TOP, // top
2312 text::VertOrientation::CENTER, // centered
2313 text::VertOrientation::BOTTOM, // bottom
2314 text::VertOrientation::LINE_TOP, // inside (obscure)
2315 text::VertOrientation::LINE_BOTTOM // outside (obscure)
2316 };
2317
2318 // #i22673# - to-line vertical alignment
2319 static const sal_Int16 aToLineVertOriTab[ nCntYAlign ] =
2320 {
2321 text::VertOrientation::NONE, // below
2322 text::VertOrientation::LINE_BOTTOM, // top
2323 text::VertOrientation::LINE_CENTER, // centered
2324 text::VertOrientation::LINE_TOP, // bottom
2325 text::VertOrientation::LINE_BOTTOM, // inside (obscure)
2326 text::VertOrientation::LINE_TOP // outside (obscure)
2327 };
2328
2329 // Adjustment is horizontally relative to...
2330 static const sal_Int16 aHoriRelOriTab[nCntRelTo] =
2331 {
2332 text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
2333 text::RelOrientation::PAGE_FRAME, // 1 is page margin
2334 text::RelOrientation::FRAME, // 2 is relative to column
2335 text::RelOrientation::CHAR // 3 is relative to character
2336 };
2337
2338 // Adjustment is vertically relative to...
2339 // #i22673# - adjustment for new vertical alignment at top of line.
2340 static const sal_Int16 aVertRelOriTab[nCntRelTo] =
2341 {
2342 text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
2343 text::RelOrientation::PAGE_FRAME, // 1 is page margin
2344 text::RelOrientation::FRAME, // 2 is relative to paragraph
2345 text::RelOrientation::TEXT_LINE // 3 is relative to line
2346 };
2347
2348 sal_Int16 eHoriOri = aHoriOriTab[ nXAlign ];
2349 sal_Int16 eHoriRel = aHoriRelOriTab[ nXRelTo ];
2350
2351 // #i36649# - adjustments for certain alignments
2352 if ( eHoriOri == text::HoriOrientation::LEFT && eHoriRel == text::RelOrientation::PAGE_FRAME )
2353 {
2354 // convert 'left to page' to 'from left -<width> to page text area'
2355 eHoriOri = text::HoriOrientation::NONE;
2356 eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
2357 const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
2358 pFSPA->nXaLeft = -nWidth;
2359 pFSPA->nXaRight = 0;
2360 }
2361 else if ( eHoriOri == text::HoriOrientation::RIGHT && eHoriRel == text::RelOrientation::PAGE_FRAME )
2362 {
2363 // convert 'right to page' to 'from left 0 to right page border'
2364 eHoriOri = text::HoriOrientation::NONE;
2365 eHoriRel = text::RelOrientation::PAGE_RIGHT;
2366 const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
2367 pFSPA->nXaLeft = 0;
2368 pFSPA->nXaRight = nWidth;
2369 }
2370
2371 // #i24255# - position of floating screen objects in
2372 // R2L layout are given in L2R layout, thus convert them of all
2373 // floating screen objects, which are imported.
2374 {
2375 // Miserable miserable hack.
2376 SwTwips nWidth = o3tl::saturating_sub(pFSPA->nXaRight, pFSPA->nXaLeft);
2377 SwTwips nLeft = pFSPA->nXaLeft;
2378 if (MiserableRTLGraphicsHack(nLeft, nWidth, eHoriOri,
2379 eHoriRel))
2380 {
2381 pFSPA->nXaLeft = nLeft;
2382 pFSPA->nXaRight = pFSPA->nXaLeft + nWidth;
2383 }
2384 }
2385
2386 // if the object is anchored inside a table cell, is horizontal aligned
2387 // at frame|character and has wrap through, but its attribute
2388 // 'layout in table cell' isn't set, convert its horizontal alignment to page text area.
2389 // #i84783# - use new method <IsObjectLayoutInTableCell()>
2390 if ( m_nInTable &&
2391 ( eHoriRel == text::RelOrientation::FRAME || eHoriRel == text::RelOrientation::CHAR ) &&
2392 pFSPA->nwr == 3 &&
2393 !IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell ) )
2394 {
2395 eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
2396 }
2397
2398 // Writer honours this wrap distance when aligned as "left" or "right",
2399 // Word doesn't. Writer doesn't honour it when its "from left".
2400 if (eHoriOri == text::HoriOrientation::LEFT)
2401 pRecord->nDxWrapDistLeft=0;
2402 else if (eHoriOri == text::HoriOrientation::RIGHT)
2403 pRecord->nDxWrapDistRight=0;
2404
2405 sal_Int16 eVertRel;
2406
2407 eVertRel = aVertRelOriTab[ nYRelTo ]; // #i18732#
2408 if ( bCurSectionVertical && nYRelTo == 2 )
2409 eVertRel = text::RelOrientation::PAGE_PRINT_AREA;
2410 // #i22673# - fill <eVertOri> in dependence of <eVertRel>
2411 sal_Int16 eVertOri;
2412 if ( eVertRel == text::RelOrientation::TEXT_LINE )
2413 {
2414 eVertOri = aToLineVertOriTab[ nYAlign ];
2415 }
2416 else
2417 {
2418 eVertOri = aVertOriTab[ nYAlign ];
2419 }
2420
2421 // Below line in word is a positive value, while in writer its
2422 // negative
2423 long nYPos = pFSPA->nYaTop;
2424 // #i22673#
2425 if ((eVertRel == text::RelOrientation::TEXT_LINE) && (eVertOri == text::VertOrientation::NONE))
2426 nYPos = -nYPos;
2427
2428 SwFormatHoriOrient aHoriOri(MakeSafePositioningValue( bCurSectionVertical ? nYPos : pFSPA->nXaLeft ),
2429 bCurSectionVertical ? eVertOri : eHoriOri,
2430 bCurSectionVertical ? eVertRel : eHoriRel);
2431 if( 4 <= nXAlign )
2432 aHoriOri.SetPosToggle(true);
2433 rFlySet.Put( aHoriOri );
2434
2435 rFlySet.Put(SwFormatVertOrient(MakeSafePositioningValue( !bCurSectionVertical ? nYPos : -pFSPA->nXaRight ),
2436 !bCurSectionVertical ? eVertOri : eHoriOri,
2437 !bCurSectionVertical ? eVertRel : eHoriRel ));
2438 }
2439
2440 return eAnchor;
2441}
2442
2443// #i84783#
2444bool SwWW8ImplReader::IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTableCell ) const
2445{
2446 bool bIsObjectLayoutInTableCell = false;
2447
2448 if ( m_bVer8 )
2449 {
2450 sal_uInt16 nWWVersion = m_xWwFib->m_nProduct & 0xE000;
2451 if (nWWVersion == 0)
2452 {
2453 // 0 nProduct can happen for Word >97 as well, check cswNew in this case instead.
2454 if (m_xWwFib->m_cswNew > 0)
2455 {
2456 // This is Word >=2000.
2457 nWWVersion = 0x2000;
2458 }
2459 }
2460
2461 switch ( nWWVersion )
2462 {
2463 case 0x0000: // version 8 aka Microsoft Word 97
2464 {
2465 bIsObjectLayoutInTableCell = false;
2466 OSL_ENSURE( nLayoutInTableCell == 0xFFFFFFFF,do { if (true && (!(nLayoutInTableCell == 0xFFFFFFFF)
)) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2467" ": "), "%s", "no explicit object attribute layout in table cell expected."
); } } while (false)
2467 "no explicit object attribute layout in table cell expected." )do { if (true && (!(nLayoutInTableCell == 0xFFFFFFFF)
)) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2467" ": "), "%s", "no explicit object attribute layout in table cell expected."
); } } while (false)
;
2468 }
2469 break;
2470 case 0x2000: // version 9 aka Microsoft Word 2000
2471 case 0x4000: // version 10 aka Microsoft Word 2002
2472 case 0x6000: // version 11 aka Microsoft Word 2003
2473 case 0x8000: // version 12 aka Microsoft Word 2007
2474 case 0xC000: // version 14 aka Microsoft Word 2010
2475 case 0xE000: // version 15 aka Microsoft Word 2013
2476 {
2477 // #i98037#
2478 // adjustment of conditions needed after deeper analysis of
2479 // certain test cases.
2480 if ( nLayoutInTableCell == 0xFFFFFFFF || // no explicit attribute value given
2481 nLayoutInTableCell == 0x80008000 ||
2482 ( nLayoutInTableCell & 0x02000000 &&
2483 !(nLayoutInTableCell & 0x80000000 ) ) )
2484 {
2485 bIsObjectLayoutInTableCell = true;
2486 }
2487 else
2488 {
2489 // Documented in [MS-ODRAW], 2.3.4.44 "Group Shape Boolean Properties".
2490 bool fUsefLayoutInCell = (nLayoutInTableCell & 0x80000000) >> 31;
2491 bool fLayoutInCell = (nLayoutInTableCell & 0x8000) >> 15;
2492 bIsObjectLayoutInTableCell = fUsefLayoutInCell && fLayoutInCell;
2493 }
2494 }
2495 break;
2496 default:
2497 {
2498 OSL_FAIL( "unknown version." )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2498" ": "), "%s", "unknown version."); } } while (false
)
;
2499 }
2500 }
2501 }
2502
2503 return bIsObjectLayoutInTableCell;
2504}
2505
2506SwFrameFormat* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp )
2507{
2508 if( m_nIniFlags & WW8FL_NO_GRAFLAYER0x8000 )
2509 return nullptr;
2510
2511 ::SetProgressState(m_nProgress, m_pDocShell); // Update
2512
2513 m_nDrawCpO = 0;
2514 m_bDrawCpOValid = m_xWwFib->GetBaseCp(m_xPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX, &m_nDrawCpO);
2515
2516 GrafikCtor();
2517
2518 WW8PLCFspecial* pPF = m_xPlcxMan->GetFdoa();
2519 if( !pPF )
2520 {
2521 OSL_ENSURE( false, "Where is the graphic (1) ?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2521" ": "), "%s", "Where is the graphic (1) ?"); } } while
(false)
;
2522 return nullptr;
2523 }
2524
2525 if( m_bVer67 )
2526 {
2527 long nOldPos = m_pStrm->Tell();
2528
2529 m_nDrawXOfs = m_nDrawYOfs = 0;
2530 ReadGrafLayer1( pPF, nGrafAnchorCp );
2531
2532 m_pStrm->Seek( nOldPos );
2533 return nullptr;
2534 }
2535
2536 // Normal case of Word 8+ version stuff
2537 pPF->SeekPos( nGrafAnchorCp );
2538
2539 WW8_FC nStartFc;
2540 void* pF0;
2541 if( !pPF->Get( nStartFc, pF0 ) ){
2542 OSL_ENSURE( false, "+Where is the graphic (2) ?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2542" ": "), "%s", "+Where is the graphic (2) ?"); } } while
(false)
;
2543 return nullptr;
2544 }
2545
2546 WW8_FSPA_SHADOW* pFS = static_cast<WW8_FSPA_SHADOW*>(pF0);
2547 WW8_FSPA* pF;
2548 WW8_FSPA aFSFA;
2549 pF = &aFSFA;
2550 WW8FSPAShadowToReal( pFS, pF );
2551 if( !pF->nSpId )
2552 {
2553 OSL_ENSURE( false, "+Where is the graphic (3) ?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2553" ": "), "%s", "+Where is the graphic (3) ?"); } } while
(false)
;
2554 return nullptr;
2555 }
2556
2557 if (!m_xMSDffManager->GetModel())
2558 m_xMSDffManager->SetModel(m_pDrawModel, 1440);
2559
2560 tools::Rectangle aRect(pF->nXaLeft, pF->nYaTop, pF->nXaRight, pF->nYaBottom);
2561 SvxMSDffImportData aData( aRect );
2562
2563 /*
2564 #i20540#
2565 The SdrOle2Obj will try and manage any ole objects it finds, causing all
2566 sorts of trouble later on
2567 */
2568 SwDocShell* pPersist = m_rDoc.GetDocShell();
2569 m_rDoc.SetDocShell(nullptr); // #i20540# Persist guard
2570
2571 SdrObject* pObject = nullptr;
2572 bool bOk = (m_xMSDffManager->GetShape(pF->nSpId, pObject, aData) && pObject);
2573
2574 m_rDoc.SetDocShell(pPersist); // #i20540# Persist guard
2575
2576 if (!bOk)
2577 {
2578 OSL_ENSURE( false, "Where is the Shape ?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2578" ": "), "%s", "Where is the Shape ?"); } } while (
false)
;
2579 return nullptr;
2580 }
2581
2582 // tdf#118375 Word relates position to the unrotated rectangle,
2583 // Writer uses the rotated one.
2584 if (pObject->GetRotateAngle())
2585 {
2586 tools::Rectangle aObjSnapRect(pObject->GetSnapRect()); // recalculates the SnapRect
2587 pF->nXaLeft = aObjSnapRect.Left();
2588 pF->nYaTop = aObjSnapRect.Top();
2589 pF->nXaRight = aObjSnapRect.Right();
2590 pF->nYaBottom = aObjSnapRect.Bottom();
2591 }
2592
2593 bool bDone = false;
2594 SdrObject* pOurNewObject = nullptr;
2595 bool bReplaceable = false;
2596
2597 switch (SdrObjKind(pObject->GetObjIdentifier()))
2598 {
2599 case OBJ_GRAF:
2600 bReplaceable = true;
2601 bDone = true;
2602 break;
2603 case OBJ_OLE2:
2604 bReplaceable = true;
2605 break;
2606 default:
2607 break;
2608
2609 }
2610
2611 // when in a header or footer word appears to treat all elements as wrap through
2612
2613 // determine wrapping mode
2614 SfxItemSet aFlySet(m_rDoc.GetAttrPool(), svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1, XATTR_START, XATTR_END>{});
2615 Reader::ResetFrameFormatAttrs(aFlySet); // tdf#122425: Explicitly remove borders and spacing
2616 css::text::WrapTextMode eSurround = css::text::WrapTextMode_PARALLEL;
2617 bool bContour = false;
2618 switch (pF->nwr)
2619 {
2620 case 0: // 0 like 2, but doesn't require absolute object
2621 case 2: // 2 wrap around absolute object
2622 eSurround = css::text::WrapTextMode_PARALLEL;
2623 break;
2624 case 1: // 1 no text next to shape
2625 eSurround = css::text::WrapTextMode_NONE;
2626 break;
2627 case 3: // 3 wrap as if no object present
2628 eSurround = css::text::WrapTextMode_THROUGH;
2629 break;
2630 case 4: // 4 wrap tightly around object
2631 case 5: // 5 wrap tightly, but allow holes
2632 eSurround = css::text::WrapTextMode_PARALLEL;
2633 bContour = true;
2634 break;
2635 }
2636
2637 // if mode 2 or 4 also regard the additional parameters
2638 if ( (2 == pF->nwr) || (4 == pF->nwr) )
2639 {
2640 switch( pF->nwrk )
2641 {
2642 // 0 wrap both sides
2643 case 0:
2644 eSurround = css::text::WrapTextMode_PARALLEL;
2645 break;
2646 // 1 wrap only on left
2647 case 1:
2648 eSurround = css::text::WrapTextMode_LEFT;
2649 break;
2650 // 2 wrap only on right
2651 case 2:
2652 eSurround = css::text::WrapTextMode_RIGHT;
2653 break;
2654 // 3 wrap only on largest side
2655 case 3:
2656 eSurround = css::text::WrapTextMode_DYNAMIC;
2657 break;
2658 }
2659 }
2660
2661 SwFormatSurround aSur( eSurround );
2662 aSur.SetContour( bContour );
2663 aSur.SetOutside(true); // Winword can only do outside contours
2664 aFlySet.Put( aSur );
2665
2666 // now position imported object correctly and so on (can be a whole group)
2667
2668 OSL_ENSURE(!((aData.size() != 1) && bReplaceable),do { if (true && (!(!((aData.size() != 1) && bReplaceable
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2669" ": "), "%s", "Replaceable drawing with > 1 entries ?"
); } } while (false)
2669 "Replaceable drawing with > 1 entries ?")do { if (true && (!(!((aData.size() != 1) && bReplaceable
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2669" ": "), "%s", "Replaceable drawing with > 1 entries ?"
); } } while (false)
;
2670
2671 if (aData.size() != 1)
2672 bReplaceable = false;
2673
2674 /*
2675 Get the record for top level object, so we can get the word anchoring
2676 and wrapping information for it.
2677 */
2678 SvxMSDffImportRec* pRecord = aData.find(pObject);
2679 OSL_ENSURE(pRecord, "how did that happen?")do { if (true && (!(pRecord))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2679" ": "), "%s", "how did that happen?"); } } while (
false)
;
2680 if (!pRecord)
2681 {
2682 // remove old object from the Z-Order list
2683 m_xMSDffManager->RemoveFromShapeOrder(pObject);
2684 // and delete the object
2685 SdrObject::Free(pObject);
2686 return nullptr;
2687 }
2688 const bool bLayoutInTableCell =
2689 m_nInTable && IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell );
2690
2691 // #i18732# - Switch on 'follow text flow', if object is laid out
2692 // inside table cell
2693 if (bLayoutInTableCell)
2694 {
2695 SwFormatFollowTextFlow aFollowTextFlow( true );
2696 aFlySet.Put( aFollowTextFlow );
2697 }
2698
2699 // #i21847#
2700 // Some shapes are set to *hidden*, don't import those ones.
2701 if (pRecord->bHidden)
2702 {
2703 // remove old object from the Z-Order list
2704 m_xMSDffManager->RemoveFromShapeOrder(pObject);
2705 // and delete the object
2706 SdrObject::Free(pObject);
2707 return nullptr;
2708 }
2709
2710 sal_uInt16 nCount = pObject->GetUserDataCount();
2711 if(nCount)
2712 {
2713 OUString lnName, aObjName, aTarFrame;
2714 for (sal_uInt16 i = 0; i < nCount; i++ )
2715 {
2716 SdrObjUserData* pData = pObject->GetUserData( i );
2717 if( pData && pData->GetInventor() == SdrInventor::ScOrSwDraw
2718 && pData->GetId() == SW_UD_IMAPDATA2)
2719 {
2720 SwMacroInfo* macInf = dynamic_cast<SwMacroInfo*>(pData);
2721 if( macInf && macInf->GetShapeId() == pF->nSpId )
2722 {
2723 lnName = macInf->GetHlink();
2724 aObjName = macInf->GetName();
2725 aTarFrame = macInf->GetTarFrame();
2726 break;
2727 }
2728 }
2729 }
2730 SwFormatURL* pFormatURL = new SwFormatURL();
2731 pFormatURL->SetURL( lnName, false );
2732 if (!aObjName.isEmpty())
2733 pFormatURL->SetName(aObjName);
2734 if (!aTarFrame.isEmpty())
2735 pFormatURL->SetTargetFrameName(aTarFrame);
2736 pFormatURL->SetMap(nullptr);
2737 aFlySet.Put(*pFormatURL);
2738 }
2739
2740 // If we are to be "below text" then we are not to be opaque
2741 // #i14045# MM If we are in a header or footer then make the object transparent
2742 // Not exactly like word but close enough for now
2743
2744 // both flags <bBelowText> and <bDrawHell> have to be set to move object into the background.
2745 // #i46794# - it reveals that value of flag <bBelowText> can be neglected.
2746 const bool bMoveToBackgrd = pRecord->bDrawHell ||
2747 ( ( m_bIsHeader || m_bIsFooter ) && pF->nwr == 3 );
2748 if ( bMoveToBackgrd )
2749 aFlySet.Put(SvxOpaqueItem(RES_OPAQUE,false));
2750
2751 OUString aObjName = pObject->GetName();
2752
2753 SwFrameFormat* pRetFrameFormat = nullptr;
2754 if (bReplaceable)
2755 {
2756 // Single graphics or ole objects
2757 pRetFrameFormat = ImportReplaceableDrawables(pObject, pOurNewObject, pRecord,
2758 pF, aFlySet);
2759 }
2760 else
2761 {
2762 // Drawing objects, (e.g. ovals or drawing groups)
2763 if (pF->bRcaSimple)
2764 {
2765 pF->nbx = WW8_FSPA::RelPageBorder;
2766 pF->nby = WW8_FSPA::RelPageBorder;
2767 }
2768
2769 RndStdIds eAnchor = ProcessEscherAlign(pRecord, pF, aFlySet);
2770
2771 // Should we, and is it possible to make this into a writer textbox
2772 if ((!(m_nIniFlags1 & WW8FL_NO_FLY_FOR_TXBX1)) && pRecord->bReplaceByFly)
2773 {
2774 pRetFrameFormat = ConvertDrawTextToFly(pObject, pOurNewObject, pRecord,
2775 eAnchor, pF, aFlySet);
2776 if (pRetFrameFormat)
2777 bDone = true;
2778 }
2779
2780 if (!bDone)
2781 {
2782 sw::util::SetLayer aSetLayer(m_rDoc);
2783 if ( bMoveToBackgrd )
2784 aSetLayer.SendObjectToHell(*pObject);
2785 else
2786 aSetLayer.SendObjectToHeaven(*pObject);
2787
2788 if (!IsInlineEscherHack())
2789 {
2790 /* Need to make sure that the correct layer ordering is applied. */
2791 // pass information, if object is in page header|footer to method.
2792 m_xWWZOrder->InsertEscherObject( pObject, pF->nSpId,
2793 m_bIsHeader || m_bIsFooter );
2794 }
2795 else
2796 {
2797 m_xWWZOrder->InsertTextLayerObject(pObject);
2798 }
2799
2800 pRetFrameFormat = m_rDoc.getIDocumentContentOperations().InsertDrawObj(*m_pPaM, *pObject, aFlySet );
2801
2802 OSL_ENSURE(pRetFrameFormat->GetAnchor().GetAnchorId() ==do { if (true && (!(pRetFrameFormat->GetAnchor().GetAnchorId
() == eAnchor))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2803" ": "), "%s", "Not the anchor type requested!"); }
} while (false)
2803 eAnchor, "Not the anchor type requested!")do { if (true && (!(pRetFrameFormat->GetAnchor().GetAnchorId
() == eAnchor))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2803" ": "), "%s", "Not the anchor type requested!"); }
} while (false)
;
2804
2805 /*
2806 Insert text if necessary into textboxes contained in groups.
2807 */
2808 for (const auto& it : aData)
2809 {
2810 pRecord = it.get();
2811 if (pRecord->pObj && pRecord->aTextId.nTxBxS)
2812 { // #i52825# pRetFrameFormat can be NULL
2813 pRetFrameFormat = MungeTextIntoDrawBox(
2814 pRecord, nGrafAnchorCp, pRetFrameFormat);
2815 }
2816 }
2817 }
2818 }
2819
2820 // #i44344#, #i44681# - positioning attributes already set
2821 if ( pRetFrameFormat /*#i52825# */ && dynamic_cast< const SwDrawFrameFormat *>( pRetFrameFormat ) != nullptr )
2822 {
2823 static_cast<SwDrawFrameFormat*>(pRetFrameFormat)->PosAttrSet();
2824 }
2825 if (!IsInlineEscherHack())
2826 MapWrapIntoFlyFormat(pRecord, pRetFrameFormat);
2827
2828 // Set frame name with object name
2829 if (pRetFrameFormat /*#i52825# */)
2830 {
2831 if (!aObjName.isEmpty())
2832 pRetFrameFormat->SetName( aObjName );
2833 if (pRetFrameFormat->GetName().isEmpty())
2834 pRetFrameFormat->SetName(m_rDoc.GetUniqueDrawObjectName());
2835 }
2836 return AddAutoAnchor(pRetFrameFormat);
2837}
2838
2839SwFrameFormat *SwWW8ImplReader::AddAutoAnchor(SwFrameFormat *pFormat)
2840{
2841 /*
2842 * anchored to character at the current position will move along the
2843 * paragraph as text is added because we are at the insertion point.
2844 *
2845 * Leave to later and set the correct location then.
2846 */
2847 if (pFormat && (pFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR))
2848 {
2849 m_xAnchorStck->AddAnchor(*m_pPaM->GetPoint(), pFormat);
2850 }
2851 return pFormat;
2852}
2853
2854SwFrameFormat* SwWW8ImplReader::MungeTextIntoDrawBox(SvxMSDffImportRec *pRecord,
2855 long nGrafAnchorCp, SwFrameFormat* pRetFrameFormat)
2856{
2857 SdrObject* pTrueObject = pRecord->pObj;
2858
2859 SdrTextObj* pSdrTextObj;
2860
2861 // check for group object (e.g. two parentheses)
2862 if (SdrObjGroup* pThisGroup = dynamic_cast<SdrObjGroup*>( pRecord->pObj) )
2863 {
2864 // Group objects don't have text. Insert a text object into
2865 // the group for holding the text.
2866 pSdrTextObj = new SdrRectObj(
2867 *m_pDrawModel,
2868 OBJ_TEXT,
2869 pThisGroup->GetCurrentBoundRect());
2870
2871 SfxItemSet aSet(m_pDrawModel->GetItemPool());
2872 aSet.Put(XFillStyleItem(drawing::FillStyle_NONE));
2873 aSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
2874 aSet.Put(SdrTextFitToSizeTypeItem( drawing::TextFitToSizeType_NONE ));
2875 aSet.Put(makeSdrTextAutoGrowHeightItem(false));
2876 aSet.Put(makeSdrTextAutoGrowWidthItem(false));
2877 pSdrTextObj->SetMergedItemSet(aSet);
2878 pSdrTextObj->NbcSetLayer( pThisGroup->GetLayer() );
2879 pThisGroup->GetSubList()->NbcInsertObject(pSdrTextObj);
2880 }
2881 else
2882 pSdrTextObj = dynamic_cast<SdrTextObj*>( pRecord->pObj );
2883
2884 if( pSdrTextObj )
2885 {
2886 Size aObjSize(pSdrTextObj->GetSnapRect().GetWidth(),
2887 pSdrTextObj->GetSnapRect().GetHeight());
2888
2889 // Object is part of a group?
2890 SdrObject* pGroupObject = pSdrTextObj->getParentSdrObjectFromSdrObject();
2891
2892 const size_t nOrdNum = pSdrTextObj->GetOrdNum();
2893 bool bEraseThisObject;
2894 InsertTxbxText( pSdrTextObj, &aObjSize, pRecord->aTextId.nTxBxS,
2895 pRecord->aTextId.nSequence, nGrafAnchorCp, pRetFrameFormat,
2896 (pSdrTextObj != pTrueObject) || (nullptr != pGroupObject),
2897 bEraseThisObject, nullptr, nullptr, nullptr, nullptr, pRecord);
2898
2899 // was this object replaced ??
2900 if (bEraseThisObject)
2901 {
2902 if( pGroupObject || (pSdrTextObj != pTrueObject) )
2903 {
2904 // Object is already replaced by a new SdrGrafObj (in the group
2905 // and) the Drawing-Page.
2906
2907 SdrObject* pNewObj = pGroupObject ?
2908 pGroupObject->GetSubList()->GetObj(nOrdNum) : pTrueObject;
2909 if (pSdrTextObj != pNewObj)
2910 {
2911 // Replace object in the Z-Order-List
2912 m_xMSDffManager->ExchangeInShapeOrder(pSdrTextObj, 0, pNewObj);
2913 // now delete object
2914 SdrObject::Free( pRecord->pObj );
2915 // and save the new object.
2916 pRecord->pObj = pNewObj;
2917 }
2918 }
2919 else
2920 {
2921 // remove the object from Z-Order list
2922 m_xMSDffManager->RemoveFromShapeOrder( pSdrTextObj );
2923 // take the object from the drawing page
2924 if( pSdrTextObj->getSdrPageFromSdrObject() )
2925 m_pDrawPg->RemoveObject( pSdrTextObj->GetOrdNum() );
2926 // and delete FrameFormat, because replaced by graphic
2927 // (this also deletes the object)
2928 m_rDoc.DelFrameFormat( pRetFrameFormat );
2929 pRetFrameFormat = nullptr;
2930 // also delete the object record
2931 pRecord->pObj = nullptr;
2932 }
2933 }
2934 else
2935 {
2936 // use ww8-default border distance
2937 SfxItemSet aItemSet(m_pDrawModel->GetItemPool(),
2938 svl::Items<SDRATTR_TEXT_LEFTDIST, SDRATTR_TEXT_LOWERDIST>{});
2939 aItemSet.Put( makeSdrTextLeftDistItem( pRecord->nDxTextLeft ) );
2940 aItemSet.Put( makeSdrTextRightDistItem( pRecord->nDxTextRight ) );
2941 aItemSet.Put( makeSdrTextUpperDistItem( pRecord->nDyTextTop ) );
2942 aItemSet.Put( makeSdrTextLowerDistItem( pRecord->nDyTextBottom ) );
2943 pSdrTextObj->SetMergedItemSetAndBroadcast(aItemSet);
2944 }
2945 }
2946 return pRetFrameFormat;
2947}
2948
2949SwFlyFrameFormat* SwWW8ImplReader::ConvertDrawTextToFly(SdrObject* &rpObject,
2950 SdrObject* &rpOurNewObject, SvxMSDffImportRec const * pRecord, RndStdIds eAnchor,
2951 WW8_FSPA const *pF, SfxItemSet &rFlySet)
2952{
2953 SwFlyFrameFormat* pRetFrameFormat = nullptr;
2954 long nStartCp;
2955 long nEndCp;
2956
2957 // Check if this textbox chain contains text as conversion of an empty
2958 // chain would not make sense.
2959 if ( TxbxChainContainsRealText(pRecord->aTextId.nTxBxS,nStartCp,nEndCp) )
2960 {
2961 // The Text is not read into SdrTextObj! Rather insert a frame and
2962 // insert the text from nStartCp to nEndCp.
2963
2964 // More attributes can be used in a frame compared to the
2965 // Edit-Engine, and it can contain field, OLEs or graphics...
2966 tools::Rectangle aInnerDist(pRecord->nDxTextLeft, pRecord->nDyTextTop,
2967 pRecord->nDxTextRight, pRecord->nDyTextBottom);
2968
2969 SwFormatFrameSize aFrameSize(SwFrameSize::Fixed, pF->nXaRight - pF->nXaLeft, pF->nYaBottom - pF->nYaTop);
2970 aFrameSize.SetWidthSizeType(pRecord->bAutoWidth ? SwFrameSize::Variable : SwFrameSize::Fixed);
2971 rFlySet.Put(aFrameSize);
2972
2973 MatchSdrItemsIntoFlySet( rpObject, rFlySet, pRecord->eLineStyle,
2974 pRecord->eLineDashing, pRecord->eShapeType, aInnerDist );
2975
2976 SdrTextObj *pSdrTextObj = dynamic_cast<SdrTextObj*>(rpObject);
2977 if (pSdrTextObj && pSdrTextObj->IsVerticalWriting())
2978 rFlySet.Put(SvxFrameDirectionItem(SvxFrameDirection::Vertical_RL_TB, RES_FRAMEDIR));
2979
2980 pRetFrameFormat = m_rDoc.MakeFlySection(eAnchor, m_pPaM->GetPoint(), &rFlySet);
2981 OSL_ENSURE(pRetFrameFormat->GetAnchor().GetAnchorId() == eAnchor,do { if (true && (!(pRetFrameFormat->GetAnchor().GetAnchorId
() == eAnchor))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2982" ": "), "%s", "Not the anchor type requested!"); }
} while (false)
2982 "Not the anchor type requested!")do { if (true && (!(pRetFrameFormat->GetAnchor().GetAnchorId
() == eAnchor))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "2982" ": "), "%s", "Not the anchor type requested!"); }
} while (false)
;
2983
2984 // if everything is OK, find pointer on new object and correct
2985 // Z-order list (or delete entry)
2986 rpOurNewObject = CreateContactObject(pRetFrameFormat);
2987
2988 // remove old object from the Z-Order list
2989 m_xMSDffManager->RemoveFromShapeOrder( rpObject );
2990
2991 // and delete the object
2992 SdrObject::Free( rpObject );
2993 /*
2994 NB: only query pOrgShapeObject starting here!
2995 */
2996
2997 if (rpOurNewObject)
2998 {
2999 /*
3000 We do not store our rpOutNewObject in the ShapeOrder because we
3001 have a FrameFormat from which we can regenerate the contact object when
3002 we need it. Because, we can have frames anchored to paragraphs in
3003 header/footers and we can copy header/footers, if we do copy a
3004 header/footer with a nonpage anchored frame in it then the contact
3005 objects are invalidated. Under this condition the FrameFormat will be
3006 updated to reflect this change and can be used to get a new
3007 contact object, while a raw rpOutNewObject stored here becomes
3008 deleted and useless.
3009 */
3010 m_xMSDffManager->StoreShapeOrder(pF->nSpId,
3011 (static_cast<sal_uLong>(pRecord->aTextId.nTxBxS) << 16) +
3012 pRecord->aTextId.nSequence, nullptr, pRetFrameFormat);
3013
3014 // The Contact object has to be inserted into the draw page, so
3015 // SwWW8ImplReader::LoadDoc1() can determine the z-order.
3016 if (!rpOurNewObject->IsInserted())
3017 {
3018 // pass information, if object is in page header|footer to method.
3019 m_xWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
3020 m_bIsHeader || m_bIsFooter );
3021 }
3022 }
3023
3024 // Box-0 receives the text for the whole chain!
3025 if( !pRecord->aTextId.nSequence )
3026 {
3027 // save flags etc and reset them
3028 WW8ReaderSave aSave( this );
3029
3030 MoveInsideFly(pRetFrameFormat);
3031
3032 m_xWWZOrder->InsideEscher(pF->nSpId);
3033
3034 // read in the text
3035 m_bTxbxFlySection = true;
3036 bool bJoined = ReadText(nStartCp, (nEndCp-nStartCp),
3037 MAN_MAINTEXT == m_xPlcxMan->GetManType() ?
3038 MAN_TXBX : MAN_TXBX_HDFT);
3039
3040 m_xWWZOrder->OutsideEscher();
3041
3042 MoveOutsideFly(pRetFrameFormat, aSave.GetStartPos(),!bJoined);
3043
3044 aSave.Restore( this );
3045
3046 StripNegativeAfterIndent(pRetFrameFormat);
3047 }
3048
3049 }
3050 return pRetFrameFormat;
3051}
3052
3053void MatchEscherMirrorIntoFlySet(const SvxMSDffImportRec &rRecord,
3054 SfxItemSet &rFlySet)
3055{
3056 if (rRecord.bVFlip || rRecord.bHFlip)
3057 {
3058 MirrorGraph eType(MirrorGraph::Dont);
3059 if (rRecord.bVFlip && rRecord.bHFlip)
3060 eType = MirrorGraph::Both;
3061 else if (rRecord.bVFlip)
3062 eType = MirrorGraph::Horizontal;
3063 else
3064 eType = MirrorGraph::Vertical;
3065 rFlySet.Put( SwMirrorGrf(eType) );
3066 }
3067}
3068
3069SwFlyFrameFormat* SwWW8ImplReader::ImportReplaceableDrawables( SdrObject* &rpObject,
3070 SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, WW8_FSPA *pF,
3071 SfxItemSet &rFlySet )
3072{
3073 SwFlyFrameFormat* pRetFrameFormat = nullptr;
3074 sal_Int32 nWidthTw = o3tl::saturating_sub(pF->nXaRight, pF->nXaLeft);
3075 if (0 > nWidthTw)
3076 nWidthTw = 0;
3077 sal_Int32 nHeightTw = o3tl::saturating_sub(pF->nYaBottom, pF->nYaTop);
3078 if (0 > nHeightTw)
3079 nHeightTw = 0;
3080
3081 ProcessEscherAlign(pRecord, pF, rFlySet);
3082
3083 rFlySet.Put(SwFormatFrameSize(SwFrameSize::Fixed, nWidthTw, nHeightTw));
3084
3085 SfxItemSet aGrSet(m_rDoc.GetAttrPool(), svl::Items<RES_GRFATR_BEGIN, RES_GRFATR_END-1>{});
3086
3087 if (pRecord)
3088 {
3089 // Note that the escher inner distance only seems to be honoured in
3090 // word for textboxes, not for graphics and ole objects.
3091 tools::Rectangle aInnerDist(0, 0, 0, 0);
3092
3093 MatchSdrItemsIntoFlySet(rpObject, rFlySet, pRecord->eLineStyle,
3094 pRecord->eLineDashing, pRecord->eShapeType, aInnerDist);
3095
3096 MatchEscherMirrorIntoFlySet(*pRecord, aGrSet);
3097 }
3098
3099 OUString aObjectName(rpObject->GetName());
3100 if (OBJ_OLE2 == SdrObjKind(rpObject->GetObjIdentifier()))
3101 pRetFrameFormat = InsertOle(*static_cast<SdrOle2Obj*>(rpObject), rFlySet, &aGrSet);
3102 else
3103 {
3104 const SdrGrafObj *pGrf = static_cast<const SdrGrafObj*>(rpObject);
3105 bool bDone = false;
3106 if (pGrf->IsLinkedGraphic() && !pGrf->GetFileName().isEmpty())
3107 {
3108 GraphicType eType = pGrf->GetGraphicType();
3109 OUString aGrfName(
3110 URIHelper::SmartRel2Abs(
3111 INetURLObject(m_sBaseURL), pGrf->GetFileName(),
3112 URIHelper::GetMaybeFileHdl()));
3113 // correction of fix for issue #i10939#:
3114 // One of the two conditions have to be true to insert the graphic
3115 // as a linked graphic -
3116 if (GraphicType::NONE == eType || CanUseRemoteLink(aGrfName))
3117 {
3118 pRetFrameFormat = m_rDoc.getIDocumentContentOperations().InsertGraphic(
3119 *m_pPaM, aGrfName, OUString(), nullptr,
3120 &rFlySet, &aGrSet, nullptr);
3121 bDone = true;
3122 }
3123 }
3124 if (!bDone)
3125 {
3126 const Graphic& rGraph = pGrf->GetGraphic();
3127 pRetFrameFormat = m_rDoc.getIDocumentContentOperations().InsertGraphic(
3128 *m_pPaM, OUString(), OUString(), &rGraph,
3129 &rFlySet, &aGrSet, nullptr);
3130 }
3131 }
3132
3133 if (pRetFrameFormat)
3134 {
3135 if( pRecord )
3136 {
3137 if( OBJ_OLE2 != SdrObjKind(rpObject->GetObjIdentifier()) )
3138 SetAttributesAtGrfNode( pRecord, pRetFrameFormat, pF );
3139 }
3140 // avoid multiple occurrences of the same graphic name
3141 m_aGrfNameGenerator.SetUniqueGraphName(pRetFrameFormat, aObjectName);
3142 }
3143 // if everything is OK, determine pointer to new object and correct
3144 // Z-Order-List accordingly (or delete entry)
3145 rpOurNewObject = CreateContactObject(pRetFrameFormat);
3146
3147 // remove old object from Z-Order-List
3148 m_xMSDffManager->RemoveFromShapeOrder( rpObject );
3149 // remove from Drawing-Page
3150 if( rpObject->getSdrPageFromSdrObject() )
3151 m_pDrawPg->RemoveObject( rpObject->GetOrdNum() );
3152
3153 // and delete the object
3154 SdrObject::Free( rpObject );
3155 /*
3156 Warning: from now on query only pOrgShapeObject!
3157 */
3158
3159 // add Contact-Object to the Z-Order-List and the page
3160 if (rpOurNewObject)
3161 {
3162 if (!m_bHdFtFootnoteEdn)
3163 m_xMSDffManager->StoreShapeOrder(pF->nSpId, 0, rpOurNewObject );
3164
3165 // The Contact-Object MUST be set in the Draw-Page, so that in
3166 // SwWW8ImplReader::LoadDoc1() the Z-Order can be defined !!!
3167 if (!rpOurNewObject->IsInserted())
3168 {
3169 // pass information, if object is in page header|footer to method.
3170 m_xWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
3171 m_bIsHeader || m_bIsFooter );
3172 }
3173 }
3174 return pRetFrameFormat;
3175}
3176
3177void SwWW8ImplReader::GrafikCtor() // For SVDraw and VCControls and Escher
3178{
3179 if (m_pDrawModel)
3180 return;
3181
3182 m_rDoc.getIDocumentDrawModelAccess().GetOrCreateDrawModel(); // #i52858# - method name changed
3183 m_pDrawModel = m_rDoc.getIDocumentDrawModelAccess().GetDrawModel();
3184 OSL_ENSURE(m_pDrawModel, "Cannot create DrawModel")do { if (true && (!(m_pDrawModel))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "3184" ": "), "%s", "Cannot create DrawModel"); } } while
(false)
;
3185 m_pDrawPg = m_pDrawModel->GetPage(0);
3186
3187 m_xMSDffManager.reset(new SwMSDffManager(*this, m_bSkipImages));
3188 m_xMSDffManager->SetModel(m_pDrawModel, 1440);
3189 /*
3190 Now the dff manager always needs a controls converter as well, but a
3191 control converter may still exist without a dffmanager.
3192 */
3193 m_xFormImpl.reset(new SwMSConvertControls(m_pDocShell, m_pPaM));
3194
3195 m_xWWZOrder.reset(new wwZOrderer(sw::util::SetLayer(m_rDoc), m_pDrawPg,
3196 m_xMSDffManager->GetShapeOrders()));
3197}
3198
3199void SwWW8ImplReader::GrafikDtor()
3200{
3201 m_pDrawEditEngine.reset(); // maybe created by graphic
3202 m_xWWZOrder.reset(); // same
3203}
3204
3205void SwWW8FltAnchorStack::AddAnchor(const SwPosition& rPos, SwFrameFormat *pFormat)
3206{
3207 OSL_ENSURE(pFormat->GetAnchor().GetAnchorId() != RndStdIds::FLY_AS_CHAR,do { if (true && (!(pFormat->GetAnchor().GetAnchorId
() != RndStdIds::FLY_AS_CHAR))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "3208" ": "), "%s", "Don't use fltanchors with inline frames, slap!"
); } } while (false)
3208 "Don't use fltanchors with inline frames, slap!")do { if (true && (!(pFormat->GetAnchor().GetAnchorId
() != RndStdIds::FLY_AS_CHAR))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8graf.cxx"
":" "3208" ": "), "%s", "Don't use fltanchors with inline frames, slap!"
); } } while (false)
;
3209 NewAttr(rPos, SwFltAnchor(pFormat));
3210}
3211
3212void SwWW8FltAnchorStack::Flush()
3213{
3214 size_t nCnt = size();
3215 for (size_t i=0; i < nCnt; ++i)
3216 {
3217 SwFltStackEntry &rEntry = (*this)[i];
3218 SwPosition aDummy(rEntry.m_aMkPos.m_nNode);
3219 SetAttrInDoc(aDummy, rEntry);
3220 DeleteAndDestroy(i--);
3221 --nCnt;
3222 }
3223}
3224
3225/* vim:set shiftwidth=4 softtabstop=4 expandtab: */