LibreOffice Module writerfilter (master) 1
GraphicHelpers.cxx
Go to the documentation of this file.
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 "GraphicHelpers.hxx"
21#include "TagLogger.hxx"
23#include "PropertyIds.hxx"
24
25#include <ooxml/resourceids.hxx>
26
27#include <com/sun/star/text/HoriOrientation.hpp>
28#include <com/sun/star/text/VertOrientation.hpp>
29#include <com/sun/star/text/RelOrientation.hpp>
30
32#include <sal/log.hxx>
33#include <svx/dialmgr.hxx>
34#include <svx/strings.hrc>
36
37#include <iostream>
38
39namespace writerfilter::dmapper {
40
41using namespace com::sun::star;
42
43PositionHandler::PositionHandler( std::pair<OUString, OUString>& rPositionOffsets, std::pair<OUString, OUString>& rAligns ) :
44LoggedProperties("PositionHandler"),
45m_nOrient(text::VertOrientation::NONE),
46m_nRelation(text::RelOrientation::FRAME),
48m_rPositionOffsets(rPositionOffsets),
49m_rAligns(rAligns)
50{
51}
52
54{
55}
56
58{
59 sal_Int32 nIntValue = rVal.getInt( );
60 switch ( aName )
61 {
62 case NS_ooxml::LN_CT_PosV_relativeFrom:
63 {
64 switch ( nIntValue )
65 {
66 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_margin:
67 m_nRelation = text::RelOrientation::PAGE_PRINT_AREA;
68 break;
69
70 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_page:
71 m_nRelation = text::RelOrientation::PAGE_FRAME;
72 break;
73
74 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_topMargin:
75 m_nRelation = text::RelOrientation::PAGE_PRINT_AREA_TOP;
76 break;
77
78 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_bottomMargin:
79 m_nRelation = text::RelOrientation::PAGE_PRINT_AREA_BOTTOM;
80 break;
81
82 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_paragraph:
84 break;
85
86 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromV_line:
87 m_nRelation = text::RelOrientation::TEXT_LINE;
88 break;
89
90 // TODO There are some other unhandled values
91 default:
92 SAL_WARN("writerfilter", "unhandled case (" << nIntValue << ") in NS_ooxml::LN_CT_PosV_relativeFrom");
93 }
94 }
95 break;
96
97 case NS_ooxml::LN_CT_PosH_relativeFrom:
98 {
99 switch ( nIntValue )
100 {
101 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_margin:
102 m_nRelation = text::RelOrientation::PAGE_PRINT_AREA;
103 break;
104
105 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_page:
106 m_nRelation = text::RelOrientation::PAGE_FRAME;
107 break;
108
109 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_insideMargin:
110 m_nRelation = text::RelOrientation::PAGE_FRAME;
111 m_bPageToggle = true;
112 break;
113
114 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_column:
116 break;
117
118 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_character:
119 m_nRelation = text::RelOrientation::CHAR;
120 break;
121
122 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_leftMargin:
123 m_nRelation = text::RelOrientation::PAGE_LEFT;
124 break;
125
126 case NS_ooxml::LN_Value_wordprocessingDrawing_ST_RelFromH_rightMargin:
127 m_nRelation = text::RelOrientation::PAGE_RIGHT;
128 break;
129
130 // TODO There are some other unhandled values
131 default:
132 SAL_WARN("writerfilter", "unhandled case (" << nIntValue << ") in NS_ooxml::LN_CT_PosH_relativeFrom");
133 }
134 }
135 break;
136 default:
137#ifdef DBG_UTIL
138 TagLogger::getInstance().element("unhandled");
139#endif
140 break;
141 }
142}
143
145{
146 sal_uInt32 nSprmId = rSprm.getId();
147
148 switch (nSprmId)
149 {
150 case NS_ooxml::LN_CT_PosH_posOffset:
152 m_rPositionOffsets.first.clear();
153 break;
154 case NS_ooxml::LN_CT_PosV_posOffset:
156 m_rPositionOffsets.second.clear();
157 break;
158 case NS_ooxml::LN_CT_PosH_align:
159 {
160 OUString& rAlign = m_rAligns.first;
161 if (rAlign == "left")
162 m_nOrient = text::HoriOrientation::LEFT;
163 else if (rAlign == "right")
164 m_nOrient = text::HoriOrientation::RIGHT;
165 else if (rAlign == "center")
166 m_nOrient = text::HoriOrientation::CENTER;
167 else if (rAlign == "inside")
168 m_nOrient = text::HoriOrientation::INSIDE;
169 else if (rAlign == "outside")
170 m_nOrient = text::HoriOrientation::OUTSIDE;
171 rAlign.clear();
172 break;
173 }
174 case NS_ooxml::LN_CT_PosV_align:
175 {
176 OUString& rAlign = m_rAligns.second;
177 if (rAlign == "top")
178 m_nOrient = text::VertOrientation::TOP;
179 else if (rAlign == "bottom")
180 m_nOrient = text::VertOrientation::BOTTOM;
181 else if (rAlign == "center")
182 m_nOrient = text::VertOrientation::CENTER;
183 else if (rAlign == "inside" && m_nRelation == text::RelOrientation::PAGE_PRINT_AREA_BOTTOM)
184 m_nOrient = text::VertOrientation::TOP;
185 else if (rAlign == "outside" && m_nRelation == text::RelOrientation::PAGE_PRINT_AREA_BOTTOM)
186 m_nOrient = text::VertOrientation::BOTTOM;
187 rAlign.clear();
188 break;
189 }
190 }
191}
192
194{
195 if( m_nRelation == text::RelOrientation::TEXT_LINE )
196 { // It appears that to 'line of text' alignment is backwards to other alignments,
197 // 'top' meaning putting on top of the line instead of having top at the line.
198 if( m_nOrient == text::VertOrientation::TOP )
199 return text::VertOrientation::BOTTOM;
200 else if( m_nOrient == text::VertOrientation::BOTTOM )
201 return text::VertOrientation::TOP;
202 }
203 return m_nOrient;
204}
205
207LoggedProperties("WrapHandler"),
208 m_nType( 0 ),
209 m_nSide( 0 )
210{
211}
212
214{
215}
216
218{
219 switch ( aName )
220 {
221 case NS_ooxml::LN_CT_Wrap_type:
222 m_nType = sal_Int32( rVal.getInt( ) );
223 break;
224 case NS_ooxml::LN_CT_Wrap_side:
225 m_nSide = sal_Int32( rVal.getInt( ) );
226 break;
227 default:;
228 }
229}
230
232{
233}
234
235text::WrapTextMode WrapHandler::getWrapMode( ) const
236{
237 // The wrap values do not map directly to our wrap mode,
238 // e.g. none in .docx actually means through in LO.
239 text::WrapTextMode nMode = text::WrapTextMode_THROUGH;
240
241 switch ( m_nType )
242 {
243 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapType_square:
244 // through and tight are somewhat complicated, approximate
245 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapType_tight:
246 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapType_through:
247 {
248 switch ( m_nSide )
249 {
250 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapSide_left:
251 nMode = text::WrapTextMode_LEFT;
252 break;
253 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapSide_right:
254 nMode = text::WrapTextMode_RIGHT;
255 break;
256 default:
257 nMode = text::WrapTextMode_PARALLEL;
258 }
259 }
260 break;
261 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapType_topAndBottom:
262 nMode = text::WrapTextMode_NONE;
263 break;
264 case NS_ooxml::LN_Value_vml_wordprocessingDrawing_ST_WrapType_none:
265 default:
266 nMode = text::WrapTextMode_THROUGH;
267 }
268
269 return nMode;
270}
271
272
273void GraphicZOrderHelper::addItem(uno::Reference<beans::XPropertySet> const& props, sal_Int32 const relativeHeight)
274{
275 m_items[ relativeHeight ] = props;
276}
277
278// The relativeHeight value in .docx is an arbitrary number, where only the relative ordering matters.
279// But in Writer, the z-order is index in 0..(numitems-1) range, so whenever a new item needs to be
280// added in the proper z-order, it is necessary to find the proper index.
281sal_Int32 GraphicZOrderHelper::findZOrder( sal_Int32 relativeHeight, bool bOldStyle )
282{
283 // std::map is iterated sorted by key
284 auto it = std::find_if(m_items.cbegin(), m_items.cend(),
285 [relativeHeight, bOldStyle](const Items::value_type& rItem) {
286 // Old-style ordering differs in what should happen when there is already an item with the same z-order:
287 // we belong under it in case of new-style, but we belong above it in case of old-style.
288 return bOldStyle ? (rItem.first > relativeHeight) : (rItem.first >= relativeHeight);
289 }
290 );
291 sal_Int32 itemZOrderOffset(0); // before the item
292 if( it == m_items.end()) // we're topmost
293 {
294 if( m_items.empty())
295 return 0;
296 --it;
297 itemZOrderOffset = 1; // after the topmost
298
299 // Check if this shape has a textbox. If so, the textbox will have its own ZOrder, so
300 // suggest a larger offset.
301 bool bTextBox = false;
302 uno::Reference<beans::XPropertySet> xShape = it->second;
303 uno::Reference<beans::XPropertySetInfo> xInfo = xShape->getPropertySetInfo();
304 if (xInfo->hasPropertyByName("TextBox"))
305 {
306 xShape->getPropertyValue("TextBox") >>= bTextBox;
307 }
308 if (bTextBox)
309 {
310 ++itemZOrderOffset;
311 }
312 }
313 // SwXFrame::getPropertyValue throws uno::RuntimeException
314 // when its GetFrameFormat() returns nullptr
315 try {
316 sal_Int32 itemZOrder(0);
317 if( it->second->getPropertyValue(getPropertyName( PROP_Z_ORDER )) >>= itemZOrder )
318 return itemZOrder + itemZOrderOffset;
319 }
320 catch (const uno::RuntimeException&) {
321 TOOLS_WARN_EXCEPTION("writerfilter", "Exception when getting item z-order");
322 }
323 SAL_WARN( "writerfilter", "findZOrder() didn't find item z-order" );
324 return 0; // this should not(?) happen
325}
326
328{
329}
330
332{
333}
334
335void ExtentHandler::attribute(Id nName, Value & rValue)
336{
337 sal_Int32 nIntValue = rValue.getInt();
338 switch (nName)
339 {
340 case NS_ooxml::LN_CT_PositiveSize2D_cx:
341 {
342 m_Extent.Width = nIntValue;
343 }
344 break;
345 case NS_ooxml::LN_CT_PositiveSize2D_cy:
346 {
347 m_Extent.Height = nIntValue;
348 }
349 break;
350 default:
351 break;
352 }
353}
354
356{
357 sal_uInt32 nSprmId = rSprm.getId();
358 switch(nSprmId)
359 {
360 case NS_ooxml::LN_CT_Inline_extent:
361 case NS_ooxml::LN_CT_Anchor_extent:
362 {
364 if( pProperties )
365 {
366 pProperties->resolve(*this);
367 }
368 }
369 break;
370 default:
371 break;
372 }
373}
374}
375
376/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 m_nPosition
An SPRM: Section, Paragraph and Run Modifier.
virtual sal_uInt32 getId() const =0
Returns id of the SPRM.
virtual writerfilter::Reference< Properties >::Pointer_t getProps()=0
Returns reference to properties contained in the SPRM.
static TagLogger & getInstance()
Definition: TagLogger.cxx:95
void element(const std::string &name)
Definition: TagLogger.cxx:102
virtual int getInt() const =0
Returns integer representation of the value.
virtual void sprm(Sprm &rSprm) override
Receives a SPRM.
virtual void attribute(Id nName, Value &rValue) override
Receives an attribute.
sal_Int32 findZOrder(sal_Int32 relativeHeight, bool bOldStyle=false)
void addItem(css::uno::Reference< css::beans::XPropertySet > const &props, sal_Int32 relativeHeight)
PositionHandler(std::pair< OUString, OUString > &rPositionOffsets, std::pair< OUString, OUString > &rAligns)
std::pair< OUString, OUString > & m_rAligns
virtual void lcl_sprm(Sprm &rSprm) override
virtual void lcl_attribute(Id aName, Value &rVal) override
std::pair< OUString, OUString > & m_rPositionOffsets
css::text::WrapTextMode getWrapMode() const
virtual void lcl_attribute(Id aName, Value &rVal) override
virtual void lcl_sprm(Sprm &rSprm) override
#define TOOLS_WARN_EXCEPTION(area, stream)
OUString aName
#define SAL_WARN(area, stream)
def text(shape, orig_st)
sal_Int32 convertEmuToHmm(sal_Int64 nValue)
dictionary props
OUString getPropertyName(PropertyIds eId)
sal_uInt32 Id