1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include "drawingml/table/tablecell.hxx"
21 #include "drawingml/table/tableproperties.hxx"
22 #include <basegfx/color/bcolor.hxx>
23 #include "oox/drawingml/shapepropertymap.hxx"
24 #include "drawingml/textbody.hxx"
25 #include "oox/drawingml/theme.hxx"
26 #include "oox/core/xmlfilterbase.hxx"
27 #include "oox/helper/propertyset.hxx"
28 #include <oox/token/namespaces.hxx>
29 #include <oox/token/properties.hxx>
30 #include <oox/token/tokens.hxx>
31 #include <tools/color.hxx>
32 #include <com/sun/star/container/XNameContainer.hpp>
33 #include <com/sun/star/beans/XMultiPropertySet.hpp>
34 #include <com/sun/star/table/XTable.hpp>
35 #include <com/sun/star/table/XMergeableCellRange.hpp>
36 #include <com/sun/star/table/BorderLineStyle.hpp>
37 #include <com/sun/star/table/BorderLine2.hpp>
38 #include <com/sun/star/drawing/LineStyle.hpp>
39 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
40 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
41 #include <com/sun/star/text/XText.hpp>
42 #include <com/sun/star/text/WritingMode.hpp>
44 using namespace ::oox::core
;
45 using namespace ::com::sun::star
;
46 using namespace ::com::sun::star::uno
;
47 using namespace ::com::sun::star::beans
;
48 using ::com::sun::star::table::BorderLine2
;
50 namespace oox
{ namespace drawingml
{ namespace table
{
52 TableCell::TableCell()
53 : mpTextBody( new TextBody() )
62 , mnVertToken( XML_horz
)
63 , mnAnchorToken( XML_t
)
64 , mbAnchorCtr( false )
65 , mnHorzOverflowToken( XML_clip
)
68 TableCell::~TableCell()
72 void applyLineAttributes( const ::oox::core::XmlFilterBase
& rFilterBase
,
73 Reference
< XPropertySet
>& rxPropSet
, oox::drawingml::LineProperties
& rLineProperties
,
76 BorderLine2 aBorderLine
;
77 if ( rLineProperties
.maLineFill
.moFillType
.differsFrom( XML_noFill
))
79 Color aColor
= rLineProperties
.maLineFill
.getBestSolidColor();
80 aBorderLine
.Color
= aColor
.getColor( rFilterBase
.getGraphicHelper() );
81 aBorderLine
.OuterLineWidth
= static_cast< sal_Int16
>( GetCoordinate( rLineProperties
.moLineWidth
.get( 0 ) ) / 4 );
82 aBorderLine
.InnerLineWidth
= static_cast< sal_Int16
>( GetCoordinate( rLineProperties
.moLineWidth
.get( 0 ) ) / 4 );
83 aBorderLine
.LineWidth
= static_cast< sal_Int16
>( GetCoordinate( rLineProperties
.moLineWidth
.get( 0 ) ) / 2 );
84 aBorderLine
.LineDistance
= 0;
86 else if ( rLineProperties
.moLineWidth
.get(0)!=0 )
88 // Default color of Line is black.
89 rLineProperties
.maLineFill
.maFillColor
.setSrgbClr( 0 );
90 aBorderLine
.OuterLineWidth
= static_cast< sal_Int16
>( GetCoordinate( rLineProperties
.moLineWidth
.get( 0 ) ) / 4 );
91 aBorderLine
.InnerLineWidth
= static_cast< sal_Int16
>( GetCoordinate( rLineProperties
.moLineWidth
.get( 0 ) ) / 4 );
92 aBorderLine
.LineWidth
= static_cast< sal_Int16
>( GetCoordinate( rLineProperties
.moLineWidth
.get( 0 ) ) / 2 );
93 aBorderLine
.LineDistance
= 0;
96 if ( rLineProperties
.moPresetDash
.has() )
98 switch ( rLineProperties
.moPresetDash
.get() )
102 aBorderLine
.LineStyle
= ::table::BorderLineStyle::DOTTED
;
107 aBorderLine
.LineStyle
= ::table::BorderLineStyle::DASHED
;
112 aBorderLine
.LineStyle
= ::table::BorderLineStyle::DASH_DOT
;
114 case XML_lgDashDotDot
:
115 case XML_sysDashDotDot
:
116 aBorderLine
.LineStyle
= ::table::BorderLineStyle::DASH_DOT_DOT
;
119 aBorderLine
.LineStyle
= ::table::BorderLineStyle::SOLID
;
122 aBorderLine
.LineStyle
= ::table::BorderLineStyle::DASHED
;
126 else if ( !rLineProperties
.maCustomDash
.empty() )
128 aBorderLine
.LineStyle
= ::table::BorderLineStyle::DASHED
;
132 aBorderLine
.LineStyle
= ::table::BorderLineStyle::NONE
;
135 PropertySet
aPropSet( rxPropSet
);
136 aPropSet
.setProperty( nPropId
, aBorderLine
);
139 void applyBorder( const ::oox::core::XmlFilterBase
& rFilterBase
, TableStylePart
& rTableStylePart
, sal_Int32 nLineType
, oox::drawingml::LineProperties
& rLineProperties
)
141 std::map
< sal_Int32
, ::oox::drawingml::LinePropertiesPtr
>& rPartLineBorders( rTableStylePart
.getLineBorders() );
142 ::oox::drawingml::ShapeStyleRef
& rLineStyleRef
= rTableStylePart
.getStyleRefs()[ nLineType
];
143 std::map
< sal_Int32
, ::oox::drawingml::LinePropertiesPtr
>::const_iterator
aIter( rPartLineBorders
.find( nLineType
) );
144 if ( ( aIter
!= rPartLineBorders
.end() ) && aIter
->second
.get() )
145 rLineProperties
.assignUsed( *aIter
->second
);
146 else if (rLineStyleRef
.mnThemedIdx
!= 0)
148 if (const Theme
* pTheme
= rFilterBase
.getCurrentTheme())
150 rLineProperties
.assignUsed( *pTheme
->getLineStyle(rLineStyleRef
.mnThemedIdx
) );
151 sal_Int32 nPhClr
= rLineStyleRef
.maPhClr
.getColor( rFilterBase
.getGraphicHelper() );
152 rLineProperties
.maLineFill
.maFillColor
.setSrgbClr( nPhClr
);
157 void applyTableStylePart( const ::oox::core::XmlFilterBase
& rFilterBase
,
158 oox::drawingml::FillProperties
& rFillProperties
,
159 TextCharacterProperties
& aTextCharProps
,
160 oox::drawingml::LineProperties
& rLeftBorder
,
161 oox::drawingml::LineProperties
& rRightBorder
,
162 oox::drawingml::LineProperties
& rTopBorder
,
163 oox::drawingml::LineProperties
& rBottomBorder
,
164 oox::drawingml::LineProperties
& rTopLeftToBottomRightBorder
,
165 oox::drawingml::LineProperties
& rBottomLeftToTopRightBorder
,
166 TableStylePart
& rTableStylePart
)
168 ::oox::drawingml::FillPropertiesPtr
& rPartFillPropertiesPtr( rTableStylePart
.getFillProperties() );
169 if ( rPartFillPropertiesPtr
.get() )
170 rFillProperties
.assignUsed( *rPartFillPropertiesPtr
);
173 ::oox::drawingml::ShapeStyleRef
& rFillStyleRef
= rTableStylePart
.getStyleRefs()[ XML_fillRef
];
174 const Theme
* pTheme
= rFilterBase
.getCurrentTheme();
175 if (pTheme
&& rFillStyleRef
.mnThemedIdx
!= 0 )
177 rFillProperties
.assignUsed( *pTheme
->getFillStyle( rFillStyleRef
.mnThemedIdx
) );
178 sal_Int32 nPhClr
= rFillStyleRef
.maPhClr
.getColor( rFilterBase
.getGraphicHelper() );
179 rFillProperties
.maFillColor
.setSrgbClr( nPhClr
);
183 applyBorder( rFilterBase
, rTableStylePart
, XML_left
, rLeftBorder
);
184 applyBorder( rFilterBase
, rTableStylePart
, XML_right
, rRightBorder
);
185 applyBorder( rFilterBase
, rTableStylePart
, XML_top
, rTopBorder
);
186 applyBorder( rFilterBase
, rTableStylePart
, XML_bottom
, rBottomBorder
);
187 applyBorder( rFilterBase
, rTableStylePart
, XML_tl2br
, rTopLeftToBottomRightBorder
);
188 applyBorder( rFilterBase
, rTableStylePart
, XML_tr2bl
, rBottomLeftToTopRightBorder
);
190 aTextCharProps
.maLatinFont
= rTableStylePart
.getLatinFont();
191 aTextCharProps
.maAsianFont
= rTableStylePart
.getAsianFont();
192 aTextCharProps
.maComplexFont
= rTableStylePart
.getComplexFont();
193 aTextCharProps
.maSymbolFont
= rTableStylePart
.getSymbolFont();
194 if ( rTableStylePart
.getTextColor().isUsed() )
196 aTextCharProps
.maFillProperties
.maFillColor
= rTableStylePart
.getTextColor();
197 aTextCharProps
.maFillProperties
.moFillType
.set(XML_solidFill
);
199 if( rTableStylePart
.getTextBoldStyle().is_initialized() )
200 aTextCharProps
.moBold
= *rTableStylePart
.getTextBoldStyle();
201 if( rTableStylePart
.getTextItalicStyle().is_initialized() )
202 aTextCharProps
.moItalic
= *rTableStylePart
.getTextItalicStyle();
205 void applyTableCellProperties( const Reference
< css::table::XCell
>& rxCell
, const TableCell
& rTableCell
)
207 Reference
< XPropertySet
> xPropSet( rxCell
, UNO_QUERY_THROW
);
208 xPropSet
->setPropertyValue( "TextUpperDistance", Any( static_cast< sal_Int32
>( rTableCell
.getTopMargin() / 360 ) ) );
209 xPropSet
->setPropertyValue( "TextRightDistance", Any( static_cast< sal_Int32
>( rTableCell
.getRightMargin() / 360 ) ) );
210 xPropSet
->setPropertyValue( "TextLeftDistance", Any( static_cast< sal_Int32
>( rTableCell
.getLeftMargin() / 360 ) ) );
211 xPropSet
->setPropertyValue( "TextLowerDistance", Any( static_cast< sal_Int32
>( rTableCell
.getBottomMargin() / 360 ) ) );
213 drawing::TextVerticalAdjust eVA
;
214 switch( rTableCell
.getAnchorToken() )
216 case XML_ctr
: eVA
= drawing::TextVerticalAdjust_CENTER
; break;
217 case XML_b
: eVA
= drawing::TextVerticalAdjust_BOTTOM
; break;
221 case XML_t
: eVA
= drawing::TextVerticalAdjust_TOP
; break;
223 xPropSet
->setPropertyValue( "TextVerticalAdjust", Any( eVA
) );
226 void TableCell::pushToXCell( const ::oox::core::XmlFilterBase
& rFilterBase
, const ::oox::drawingml::TextListStylePtr
& pMasterTextListStyle
,
227 const css::uno::Reference
< css::table::XCell
>& rxCell
, const TableProperties
& rTableProperties
,
228 const TableStyle
& rTableStyle
, sal_Int32 nColumn
, sal_Int32 nMaxColumn
, sal_Int32 nRow
, sal_Int32 nMaxRow
)
230 TableStyle
& rTable( const_cast< TableStyle
& >( rTableStyle
) );
231 TableProperties
& rProperties( const_cast< TableProperties
& >( rTableProperties
) );
233 Reference
< text::XText
> xText( rxCell
, UNO_QUERY_THROW
);
234 Reference
< text::XTextCursor
> xAt
= xText
->createTextCursor();
236 applyTableCellProperties( rxCell
, *this );
237 TextCharacterProperties aTextStyleProps
;
238 xAt
->gotoStart( true );
239 xAt
->gotoEnd( true );
241 Reference
< XPropertySet
> xPropSet( rxCell
, UNO_QUERY_THROW
);
242 oox::drawingml::FillProperties aFillProperties
;
243 oox::drawingml::LineProperties aLinePropertiesLeft
;
244 oox::drawingml::LineProperties aLinePropertiesRight
;
245 oox::drawingml::LineProperties aLinePropertiesTop
;
246 oox::drawingml::LineProperties aLinePropertiesBottom
;
247 oox::drawingml::LineProperties aLinePropertiesTopLeftToBottomRight
;
248 oox::drawingml::LineProperties aLinePropertiesBottomLeftToTopRight
;
250 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
252 aLinePropertiesRight
,
254 aLinePropertiesBottom
,
255 aLinePropertiesTopLeftToBottomRight
,
256 aLinePropertiesBottomLeftToTopRight
,
257 rTable
.getWholeTbl() );
259 if ( rProperties
.isFirstRow() && ( nRow
== 0 ) )
261 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
263 aLinePropertiesRight
,
265 aLinePropertiesBottom
,
266 aLinePropertiesTopLeftToBottomRight
,
267 aLinePropertiesBottomLeftToTopRight
,
268 rTable
.getFirstRow() );
270 if ( rProperties
.isLastRow() && ( nRow
== nMaxRow
) )
272 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
274 aLinePropertiesRight
,
276 aLinePropertiesBottom
,
277 aLinePropertiesTopLeftToBottomRight
,
278 aLinePropertiesBottomLeftToTopRight
,
279 rTable
.getLastRow() );
281 if ( rProperties
.isFirstCol() && ( nColumn
== 0 ) )
283 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
285 aLinePropertiesRight
,
287 aLinePropertiesBottom
,
288 aLinePropertiesTopLeftToBottomRight
,
289 aLinePropertiesBottomLeftToTopRight
,
290 rTable
.getFirstCol() );
292 if ( rProperties
.isLastCol() && ( nColumn
== nMaxColumn
) )
294 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
296 aLinePropertiesRight
,
298 aLinePropertiesBottom
,
299 aLinePropertiesTopLeftToBottomRight
,
300 aLinePropertiesBottomLeftToTopRight
,
301 rTable
.getLastCol() );
303 if ( rProperties
.isBandRow() )
305 if ( ( !rProperties
.isFirstRow() || ( nRow
!= 0 ) ) &&
306 ( !rProperties
.isLastRow() || ( nRow
!= nMaxRow
) ) &&
307 ( !rProperties
.isFirstCol() || ( nColumn
!= 0 ) ) &&
308 ( !rProperties
.isLastCol() || ( nColumn
!= nMaxColumn
) ) )
310 sal_Int32 nBand
= nRow
;
311 if ( rProperties
.isFirstRow() )
315 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
317 aLinePropertiesRight
,
319 aLinePropertiesBottom
,
320 aLinePropertiesTopLeftToBottomRight
,
321 aLinePropertiesBottomLeftToTopRight
,
322 rTable
.getBand2H() );
326 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
328 aLinePropertiesRight
,
330 aLinePropertiesBottom
,
331 aLinePropertiesTopLeftToBottomRight
,
332 aLinePropertiesBottomLeftToTopRight
,
333 rTable
.getBand1H() );
337 if ( ( nRow
== 0 ) && ( nColumn
== 0 ) )
339 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
341 aLinePropertiesRight
,
343 aLinePropertiesBottom
,
344 aLinePropertiesTopLeftToBottomRight
,
345 aLinePropertiesBottomLeftToTopRight
,
346 rTable
.getNwCell() );
348 if ( ( nRow
== nMaxRow
) && ( nColumn
== 0 ) )
350 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
352 aLinePropertiesRight
,
354 aLinePropertiesBottom
,
355 aLinePropertiesTopLeftToBottomRight
,
356 aLinePropertiesBottomLeftToTopRight
,
357 rTable
.getSwCell() );
359 if ( ( nRow
== 0 ) && ( nColumn
== nMaxColumn
) )
361 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
363 aLinePropertiesRight
,
365 aLinePropertiesBottom
,
366 aLinePropertiesTopLeftToBottomRight
,
367 aLinePropertiesBottomLeftToTopRight
,
368 rTable
.getNeCell() );
370 if ( ( nRow
== nMaxRow
) && ( nColumn
== nMaxColumn
) )
372 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
374 aLinePropertiesRight
,
376 aLinePropertiesBottom
,
377 aLinePropertiesTopLeftToBottomRight
,
378 aLinePropertiesBottomLeftToTopRight
,
379 rTable
.getSeCell() );
381 if ( rProperties
.isBandCol() )
383 if ( ( !rProperties
.isFirstRow() || ( nRow
!= 0 ) ) &&
384 ( !rProperties
.isLastRow() || ( nRow
!= nMaxRow
) ) &&
385 ( !rProperties
.isFirstCol() || ( nColumn
!= 0 ) ) &&
386 ( !rProperties
.isLastCol() || ( nColumn
!= nMaxColumn
) ) )
388 sal_Int32 nBand
= nColumn
;
389 if ( rProperties
.isFirstCol() )
393 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
395 aLinePropertiesRight
,
397 aLinePropertiesBottom
,
398 aLinePropertiesTopLeftToBottomRight
,
399 aLinePropertiesBottomLeftToTopRight
,
400 rTable
.getBand2V() );
404 applyTableStylePart( rFilterBase
, aFillProperties
, aTextStyleProps
,
406 aLinePropertiesRight
,
408 aLinePropertiesBottom
,
409 aLinePropertiesTopLeftToBottomRight
,
410 aLinePropertiesBottomLeftToTopRight
,
411 rTable
.getBand1V() );
415 aLinePropertiesLeft
.assignUsed( maLinePropertiesLeft
);
416 aLinePropertiesRight
.assignUsed( maLinePropertiesRight
);
417 aLinePropertiesTop
.assignUsed( maLinePropertiesTop
);
418 aLinePropertiesBottom
.assignUsed( maLinePropertiesBottom
);
419 aLinePropertiesTopLeftToBottomRight
.assignUsed( maLinePropertiesTopLeftToBottomRight
);
420 aLinePropertiesBottomLeftToTopRight
.assignUsed( maLinePropertiesBottomLeftToTopRight
);
421 applyLineAttributes( rFilterBase
, xPropSet
, aLinePropertiesLeft
, PROP_LeftBorder
);
422 applyLineAttributes( rFilterBase
, xPropSet
, aLinePropertiesRight
, PROP_RightBorder
);
423 applyLineAttributes( rFilterBase
, xPropSet
, aLinePropertiesTop
, PROP_TopBorder
);
424 applyLineAttributes( rFilterBase
, xPropSet
, aLinePropertiesBottom
, PROP_BottomBorder
);
425 applyLineAttributes( rFilterBase
, xPropSet
, aLinePropertiesTopLeftToBottomRight
, PROP_DiagonalTLBR
);
426 applyLineAttributes( rFilterBase
, xPropSet
, aLinePropertiesBottomLeftToTopRight
, PROP_DiagonalBLTR
);
428 aFillProperties
.assignUsed( maFillProperties
);
429 ShapePropertyMap
aPropMap( rFilterBase
.getModelObjectHelper() );
432 sal_Int32 nPhClr
= API_RGB_TRANSPARENT
;
433 std::shared_ptr
< ::oox::drawingml::FillProperties
>& rBackgroundFillPropertiesPtr( rTable
.getBackgroundFillProperties() );
434 ::oox::drawingml::ShapeStyleRef
& rBackgroundFillStyle( rTable
.getBackgroundFillStyleRef() );
435 if (rBackgroundFillPropertiesPtr
.get())
436 aBgColor
= rBackgroundFillPropertiesPtr
->getBestSolidColor();
437 else if (rBackgroundFillStyle
.mnThemedIdx
!= 0)
439 if (const Theme
* pTheme
= rFilterBase
.getCurrentTheme())
441 aBgColor
= pTheme
->getFillStyle(rBackgroundFillStyle
.mnThemedIdx
)->getBestSolidColor();
442 nPhClr
= rBackgroundFillStyle
.maPhClr
.getColor(rFilterBase
.getGraphicHelper());
445 if (aBgColor
.isUsed())
447 const Color
& rCellColor
= aFillProperties
.getBestSolidColor();
448 const double fTransparency
= rCellColor
.isUsed() ? 0.01 * rCellColor
.getTransparency() : 1.0;
449 ::Color
nBgColor( aBgColor
.getColor(rFilterBase
.getGraphicHelper(), nPhClr
) );
450 ::Color
nCellColor( rCellColor
.getColor(rFilterBase
.getGraphicHelper()) );
451 ::Color
aResult( basegfx::interpolate(nBgColor
.getBColor(), nCellColor
.getBColor(), 1.0 - fTransparency
) );
452 aFillProperties
.maFillColor
.clearTransformations();
453 aFillProperties
.maFillColor
.setSrgbClr(aResult
.GetRGBColor());
454 aFillProperties
.moFillType
.set(XML_solidFill
);
456 if (!aFillProperties
.moFillType
.has())
457 aFillProperties
.moFillType
.set(XML_noFill
);
460 aFillProperties
.pushToPropMap( aPropMap
, rFilterBase
.getGraphicHelper() );
461 PropertySet( xPropSet
).setProperties( aPropMap
);
463 if ( getVertToken() == XML_eaVert
)
465 xPropSet
->setPropertyValue("TextWritingMode", Any(css::text::WritingMode_TB_RL
));
468 getTextBody()->insertAt( rFilterBase
, xText
, xAt
, aTextStyleProps
, pMasterTextListStyle
);
470 if (getVertToken() == XML_vert
)
471 xPropSet
->setPropertyValue("RotateAngle", Any(short(27000)));
472 else if (getVertToken() == XML_vert270
)
473 xPropSet
->setPropertyValue("RotateAngle", Any(short(9000)));
478 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */