lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / writerfilter / source / dmapper / GraphicHelpers.cxx
blob4a4c73eed5800134fe3bd90ede5fb6b27835a52c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #include "ConversionHelper.hxx"
20 #include "GraphicHelpers.hxx"
21 #include <dmapper/GraphicZOrderHelper.hxx>
22 #include "PropertyIds.hxx"
24 #include <ooxml/resourceids.hxx>
26 #include <com/sun/star/text/HoriOrientation.hpp>
27 #include <com/sun/star/text/VertOrientation.hpp>
28 #include <com/sun/star/text/RelOrientation.hpp>
30 #include <oox/drawingml/drawingmltypes.hxx>
31 #include <sal/log.hxx>
32 #include <unotools/resmgr.hxx>
33 #include <vcl/settings.hxx>
34 #include <vcl/svapp.hxx>
35 #include <svx/dialmgr.hxx>
36 #include <svx/strings.hrc>
38 #include <iostream>
39 #include <memory>
41 namespace writerfilter {
42 namespace dmapper {
44 using namespace com::sun::star;
46 PositionHandler::PositionHandler( std::pair<OUString, OUString>& rPositionOffsets, std::pair<OUString, OUString>& rAligns ) :
47 LoggedProperties("PositionHandler"),
48 m_nOrient(text::VertOrientation::NONE),
49 m_nRelation(text::RelOrientation::FRAME),
50 m_nPosition(0),
51 m_rPositionOffsets(rPositionOffsets),
52 m_rAligns(rAligns)
56 PositionHandler::~PositionHandler( )
60 void PositionHandler::lcl_attribute( Id aName, Value& rVal )
62 sal_Int32 nIntValue = rVal.getInt( );
63 switch ( aName )
65 case NS_ooxml::LN_CT_PosV_relativeFrom:
67 switch ( nIntValue )
69 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_margin:
70 m_nRelation = text::RelOrientation::PAGE_PRINT_AREA;
71 break;
73 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_page:
74 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_topMargin: // fallthrough intended
75 m_nRelation = text::RelOrientation::PAGE_FRAME;
76 break;
78 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_paragraph:
79 m_nRelation = text::RelOrientation::FRAME;
80 break;
82 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_line:
83 m_nRelation = text::RelOrientation::TEXT_LINE;
84 break;
86 // TODO There are some other unhandled values
87 default:
88 SAL_WARN("writerfilter", "unhandled case (" << nIntValue << ") in NS_ooxml::LN_CT_PosV_relativeFrom");
91 break;
93 case NS_ooxml::LN_CT_PosH_relativeFrom:
95 switch ( nIntValue )
97 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_margin:
98 m_nRelation = text::RelOrientation::PAGE_PRINT_AREA;
99 break;
101 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_page:
102 m_nRelation = text::RelOrientation::PAGE_FRAME;
103 break;
105 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_column:
106 m_nRelation = text::RelOrientation::FRAME;
107 break;
109 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_character:
110 m_nRelation = text::RelOrientation::CHAR;
111 break;
113 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_leftMargin:
114 m_nRelation = text::RelOrientation::PAGE_LEFT;
115 break;
117 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_rightMargin:
118 m_nRelation = text::RelOrientation::PAGE_RIGHT;
119 break;
121 // TODO There are some other unhandled values
122 default:
123 SAL_WARN("writerfilter", "unhandled case (" << nIntValue << ") in NS_ooxml::LN_CT_PosH_relativeFrom");
126 break;
127 default:
128 #ifdef DEBUG_WRITERFILTER
129 TagLogger::getInstance().element("unhandled");
130 #endif
131 break;
135 void PositionHandler::lcl_sprm(Sprm& rSprm)
137 sal_uInt32 nSprmId = rSprm.getId();
139 switch (nSprmId)
141 case NS_ooxml::LN_CT_PosH_posOffset:
142 m_nPosition = oox::drawingml::convertEmuToHmm(m_rPositionOffsets.first.toInt32());
143 m_rPositionOffsets.first.clear();
144 break;
145 case NS_ooxml::LN_CT_PosV_posOffset:
146 m_nPosition = oox::drawingml::convertEmuToHmm(m_rPositionOffsets.second.toInt32());
147 m_rPositionOffsets.second.clear();
148 break;
149 case NS_ooxml::LN_CT_PosH_align:
151 OUString& rAlign = m_rAligns.first;
152 if (rAlign == "left")
153 m_nOrient = text::HoriOrientation::LEFT;
154 else if (rAlign == "right")
155 m_nOrient = text::HoriOrientation::RIGHT;
156 else if (rAlign == "center")
157 m_nOrient = text::HoriOrientation::CENTER;
158 else if (rAlign == "inside")
159 m_nOrient = text::HoriOrientation::INSIDE;
160 else if (rAlign == "outside")
161 m_nOrient = text::HoriOrientation::OUTSIDE;
162 rAlign.clear();
163 break;
165 case NS_ooxml::LN_CT_PosV_align:
167 OUString& rAlign = m_rAligns.second;
168 if (rAlign == "top")
169 m_nOrient = text::VertOrientation::TOP;
170 else if (rAlign == "bottom")
171 m_nOrient = text::VertOrientation::BOTTOM;
172 else if (rAlign == "center")
173 m_nOrient = text::VertOrientation::CENTER;
174 else if (rAlign == "inside")
175 m_nOrient = text::VertOrientation::NONE;
176 else if (rAlign == "outside")
177 m_nOrient = text::VertOrientation::NONE;
178 rAlign.clear();
179 break;
184 sal_Int16 PositionHandler::orientation() const
186 if( m_nRelation == text::RelOrientation::TEXT_LINE )
187 { // It appears that to 'line of text' alignment is backwards to other alignments,
188 // 'top' meaning putting on top of the line instead of having top at the line.
189 if( m_nOrient == text::VertOrientation::TOP )
190 return text::VertOrientation::BOTTOM;
191 else if( m_nOrient == text::VertOrientation::BOTTOM )
192 return text::VertOrientation::TOP;
194 return m_nOrient;
197 WrapHandler::WrapHandler( ) :
198 LoggedProperties("WrapHandler"),
199 m_nType( 0 ),
200 m_nSide( 0 )
204 WrapHandler::~WrapHandler( )
208 void WrapHandler::lcl_attribute( Id aName, Value& rVal )
210 switch ( aName )
212 case NS_ooxml::LN_CT_Wrap_type:
213 m_nType = sal_Int32( rVal.getInt( ) );
214 break;
215 case NS_ooxml::LN_CT_Wrap_side:
216 m_nSide = sal_Int32( rVal.getInt( ) );
217 break;
218 default:;
222 void WrapHandler::lcl_sprm( Sprm& )
226 text::WrapTextMode WrapHandler::getWrapMode( )
228 // The wrap values do not map directly to our wrap mode,
229 // e.g. none in .docx actually means through in LO.
230 text::WrapTextMode nMode = text::WrapTextMode_THROUGH;
232 switch ( m_nType )
234 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapType_square:
235 // through and tight are somewhat complicated, approximate
236 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapType_tight:
237 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapType_through:
239 switch ( m_nSide )
241 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapSide_left:
242 nMode = text::WrapTextMode_LEFT;
243 break;
244 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapSide_right:
245 nMode = text::WrapTextMode_RIGHT;
246 break;
247 default:
248 nMode = text::WrapTextMode_PARALLEL;
251 break;
252 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapType_topAndBottom:
253 nMode = text::WrapTextMode_NONE;
254 break;
255 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapType_none:
256 default:
257 nMode = text::WrapTextMode_THROUGH;
260 return nMode;
264 void GraphicZOrderHelper::addItem(uno::Reference<beans::XPropertySet> const& props, sal_Int32 const relativeHeight)
266 items[ relativeHeight ] = props;
269 // The relativeHeight value in .docx is an arbitrary number, where only the relative ordering matters.
270 // But in Writer, the z-order is index in 0..(numitems-1) range, so whenever a new item needs to be
271 // added in the proper z-order, it is necessary to find the proper index.
272 sal_Int32 GraphicZOrderHelper::findZOrder( sal_Int32 relativeHeight, bool bOldStyle )
274 // std::map is iterated sorted by key
275 auto it = std::find_if(items.cbegin(), items.cend(),
276 [relativeHeight, bOldStyle](const Items::value_type& rItem) {
277 // Old-style ordering differs in what should happen when there is already an item with the same z-order:
278 // we belong under it in case of new-style, but we belong above it in case of old-style.
279 return bOldStyle ? (rItem.first > relativeHeight) : (rItem.first >= relativeHeight);
282 sal_Int32 itemZOrderOffset(0); // before the item
283 if( it == items.end()) // we're topmost
285 if( items.empty())
286 return 0;
287 --it;
288 itemZOrderOffset = 1; // after the topmost
290 // SwXFrame::getPropertyValue throws uno::RuntimeException
291 // when its GetFrameFormat() returns nullptr
292 try {
293 sal_Int32 itemZOrder(0);
294 if( it->second->getPropertyValue(getPropertyName( PROP_Z_ORDER )) >>= itemZOrder )
295 return itemZOrder + itemZOrderOffset;
297 catch (const uno::RuntimeException&) {
298 SAL_WARN("writerfilter", "Exception when getting item z-order");
300 SAL_WARN( "writerfilter", "findZOrder() didn't find item z-order" );
301 return 0; // this should not(?) happen
304 GraphicNamingHelper::GraphicNamingHelper()
305 : m_nCounter(0)
309 OUString GraphicNamingHelper::NameGraphic(const OUString& rTemplate)
311 OUString aRet = rTemplate;
313 if (aRet.isEmpty())
315 // Empty template: then auto-generate a unique name.
316 OUString aPrefix(SvxResId(STR_ObjNameSingulGRAF));
317 aRet += aPrefix + OUString::number(++m_nCounter);
320 return aRet;
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */