android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / filter / xml / xmlexpit.cxx
bloba39d12228c0a4138da2de596ea98f7e3546398eb
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 .
20 #include "xmlexpit.hxx"
22 #include <osl/diagnose.h>
23 #include <rtl/ustrbuf.hxx>
24 #include <sax/tools/converter.hxx>
25 #include <svl/poolitem.hxx>
26 #include <svl/itemset.hxx>
27 #include <utility>
28 #include <xmloff/xmluconv.hxx>
29 #include <xmloff/namespacemap.hxx>
30 #include <xmloff/xmlnamespace.hxx>
31 #include <xmloff/prhdlfac.hxx>
32 #include <xmloff/xmltypes.hxx>
33 #include <editeng/xmlcnitm.hxx>
34 #include <xmloff/xmlexp.hxx>
35 #include <xmloff/xmlprhdl.hxx>
36 #include <editeng/memberids.h>
37 #include <hintids.hxx>
38 #include <unomid.h>
39 #include <svx/unomid.hxx>
40 #include <editeng/lrspitem.hxx>
41 #include <editeng/ulspitem.hxx>
42 #include <editeng/shaditem.hxx>
43 #include <editeng/boxitem.hxx>
44 #include <editeng/formatbreakitem.hxx>
45 #include <editeng/keepitem.hxx>
46 #include <editeng/brushitem.hxx>
47 #include <editeng/frmdiritem.hxx>
48 #include <editeng/prntitem.hxx>
49 #include <fmtpdsc.hxx>
50 #include <fmtornt.hxx>
51 #include <fmtfsize.hxx>
53 #include "xmlithlp.hxx"
55 #include <fmtrowsplt.hxx>
57 using ::editeng::SvxBorderLine;
58 using namespace ::com::sun::star;
59 using namespace ::xmloff::token;
60 using uno::Any;
62 // fills the given attribute list with the items in the given set
63 void SvXMLExportItemMapper::exportXML( const SvXMLExport& rExport,
64 comphelper::AttributeList& rAttrList,
65 const SfxItemSet& rSet,
66 const SvXMLUnitConverter& rUnitConverter,
67 const SvXMLNamespaceMap& rNamespaceMap,
68 std::vector<sal_uInt16> *pIndexArray ) const
70 const sal_uInt16 nCount = mrMapEntries->getCount();
71 sal_uInt16 nIndex = 0;
73 while( nIndex < nCount )
75 SvXMLItemMapEntry const & rEntry = mrMapEntries->getByIndex( nIndex );
77 // we have a valid map entry here, so lets use it...
78 if( 0 == (rEntry.nMemberId & MID_SW_FLAG_NO_ITEM_EXPORT) )
80 const SfxPoolItem* pItem = GetItem( rSet, rEntry.nWhichId );
81 // do we have an item?
82 if(pItem)
84 if( 0 != (rEntry.nMemberId & MID_SW_FLAG_ELEMENT_ITEM_EXPORT) )
86 // element items do not add any properties,
87 // we export it later
88 if( pIndexArray )
89 pIndexArray->push_back( nIndex );
92 else
94 exportXML( rExport, rAttrList, *pItem, rEntry, rUnitConverter,
95 rNamespaceMap, &rSet );
99 else
101 OSL_FAIL( "no item not handled in xml export" );
103 nIndex++;
107 void SvXMLExportItemMapper::exportXML(const SvXMLExport&,
108 comphelper::AttributeList& rAttrList,
109 const SfxPoolItem& rItem,
110 const SvXMLItemMapEntry& rEntry,
111 const SvXMLUnitConverter& rUnitConverter,
112 const SvXMLNamespaceMap& rNamespaceMap,
113 const SfxItemSet *pSet ) const
115 if( 0 != (rEntry.nMemberId & MID_SW_FLAG_SPECIAL_ITEM_EXPORT) )
117 if( dynamic_cast<const SwFormatRowSplit*>( &rItem) != nullptr )
119 OUString aValue;
120 bool bAddAttribute = true;
121 if( rEntry.nNameSpace == XML_NAMESPACE_STYLE )
123 bAddAttribute = false;
125 else
127 OUStringBuffer aOut;
128 const SfxBoolItem* pSplit = dynamic_cast<const SfxBoolItem*>( &rItem );
129 assert(pSplit && "Wrong Which-ID");
130 const sal_uInt16 eEnum = (pSplit && pSplit->GetValue()) ? 1 : 0;
131 SvXMLUnitConverter::convertEnum( aOut, eEnum, aXML_KeepTogetherType );
132 aValue = aOut.makeStringAndClear();
134 if( bAddAttribute )
136 const OUString sName( rNamespaceMap.GetQNameByKey( rEntry.nNameSpace,
137 GetXMLToken(rEntry.eLocalName) ) );
138 rAttrList.AddAttribute( sName, aValue );
142 if (const SvXMLAttrContainerItem *pUnknown = dynamic_cast<const SvXMLAttrContainerItem*>(&rItem))
144 std::unique_ptr<SvXMLNamespaceMap> pNewNamespaceMap;
145 const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap;
147 const sal_uInt16 nCount = pUnknown->GetAttrCount();
148 for( sal_uInt16 i=0; i < nCount; i++ )
150 const OUString sPrefix( pUnknown->GetAttrPrefix( i ) );
151 if( !sPrefix.isEmpty() )
153 const OUString sNamespace( pUnknown->GetAttrNamespace( i ) );
155 // if the prefix isn't defined yet or has another meaning,
156 // we have to redefine it now.
157 const sal_uInt16 nIdx = pNamespaceMap->GetIndexByPrefix( sPrefix );
158 if( USHRT_MAX == nIdx ||
159 pNamespaceMap->GetNameByIndex( nIdx ) != sNamespace )
161 if( !pNewNamespaceMap )
163 pNewNamespaceMap.reset(
164 new SvXMLNamespaceMap( rNamespaceMap ));
165 pNamespaceMap = pNewNamespaceMap.get();
167 pNewNamespaceMap->Add( sPrefix, sNamespace );
169 rAttrList.AddAttribute( GetXMLToken(XML_XMLNS) + ":" + sPrefix,
170 sNamespace );
173 rAttrList.AddAttribute( sPrefix + ":" + pUnknown->GetAttrLName(i),
174 pUnknown->GetAttrValue(i) );
176 else
178 rAttrList.AddAttribute( pUnknown->GetAttrLName(i),
179 pUnknown->GetAttrValue(i) );
183 else
185 handleSpecialItem( rAttrList, rEntry, rItem, rUnitConverter,
186 rNamespaceMap, pSet );
189 else if( 0 == (rEntry.nMemberId & MID_SW_FLAG_ELEMENT_ITEM_EXPORT) )
191 bool bDone = false;
192 switch (rItem.Which())
194 case RES_FRAMEDIR:
196 // Write bt-lr and tb-rl90 to the extension namespace, handle other values
197 // below.
198 auto pDirection = static_cast<const SvxFrameDirectionItem*>(&rItem);
199 if (rEntry.nNameSpace == XML_NAMESPACE_LO_EXT
200 && pDirection->GetValue() == SvxFrameDirection::Vertical_LR_BT)
202 const OUString sName(rNamespaceMap.GetQNameByKey(
203 XML_NAMESPACE_LO_EXT, GetXMLToken(XML_WRITING_MODE)));
204 rAttrList.AddAttribute(sName, GetXMLToken(XML_BT_LR));
206 if (rEntry.nNameSpace == XML_NAMESPACE_LO_EXT
207 || pDirection->GetValue() == SvxFrameDirection::Vertical_LR_BT)
208 bDone = true;
210 if (rEntry.nNameSpace == XML_NAMESPACE_LO_EXT
211 && pDirection->GetValue() == SvxFrameDirection::Vertical_RL_TB90)
213 const OUString sName(rNamespaceMap.GetQNameByKey(
214 XML_NAMESPACE_LO_EXT, GetXMLToken(XML_WRITING_MODE)));
215 rAttrList.AddAttribute(sName, GetXMLToken(XML_TB_RL90));
217 if (rEntry.nNameSpace == XML_NAMESPACE_LO_EXT
218 || pDirection->GetValue() == SvxFrameDirection::Vertical_RL_TB90)
219 bDone = true;
220 break;
224 if (!bDone)
226 OUString aValue;
227 if( QueryXMLValue(rItem, aValue,
228 static_cast< sal_uInt16 >(
229 rEntry.nMemberId & MID_SW_FLAG_MASK ),
230 rUnitConverter ) )
232 const OUString sName(
233 rNamespaceMap.GetQNameByKey( rEntry.nNameSpace,
234 GetXMLToken(rEntry.eLocalName)));
235 rAttrList.AddAttribute( sName, aValue );
241 void SvXMLExportItemMapper::exportElementItems(
242 SvXMLExport& rExport,
243 const SfxItemSet &rSet,
244 const std::vector<sal_uInt16> &rIndexArray ) const
246 const size_t nCount = rIndexArray.size();
248 bool bItemsExported = false;
249 for( size_t nIndex = 0; nIndex < nCount; ++nIndex )
251 const sal_uInt16 nElement = rIndexArray[ nIndex ];
252 SvXMLItemMapEntry const & rEntry = mrMapEntries->getByIndex( nElement );
253 OSL_ENSURE( 0 != (rEntry.nMemberId & MID_SW_FLAG_ELEMENT_ITEM_EXPORT),
254 "wrong mid flag!" );
256 const SfxPoolItem* pItem = GetItem( rSet, rEntry.nWhichId );
257 // do we have an item?
258 if(pItem)
260 rExport.IgnorableWhitespace();
261 handleElementItem( rEntry, *pItem );
262 bItemsExported = true;
266 if( bItemsExported )
267 rExport.IgnorableWhitespace();
270 /** returns the item with the given WhichId from the given ItemSet if it's
273 const SfxPoolItem* SvXMLExportItemMapper::GetItem( const SfxItemSet& rSet,
274 sal_uInt16 nWhichId)
276 // first get item from itemset
277 const SfxPoolItem* pItem;
278 SfxItemState eState = rSet.GetItemState( nWhichId, false, &pItem );
280 if( SfxItemState::SET == eState )
282 return pItem;
284 else
286 return nullptr;
290 SvXMLExportItemMapper::SvXMLExportItemMapper( SvXMLItemMapEntriesRef rMapEntries )
291 : mrMapEntries(std::move(rMapEntries))
295 SvXMLExportItemMapper::~SvXMLExportItemMapper()
299 void SvXMLExportItemMapper::exportXML( SvXMLExport& rExport,
300 const SfxItemSet& rSet,
301 const SvXMLUnitConverter& rUnitConverter,
302 XMLTokenEnum ePropToken ) const
304 std::vector<sal_uInt16> aIndexArray;
306 exportXML( rExport, rExport.GetAttrList(), rSet, rUnitConverter,
307 rExport.GetNamespaceMap(), &aIndexArray );
309 if( rExport.GetAttrList().getLength() > 0 || !aIndexArray.empty() )
311 rExport.IgnorableWhitespace();
313 SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, ePropToken,
314 false, false );
315 exportElementItems( rExport, rSet, aIndexArray );
319 /** this method is called for every item that has the
320 MID_SW_FLAG_SPECIAL_ITEM_EXPORT flag set */
321 void SvXMLExportItemMapper::handleSpecialItem( comphelper::AttributeList& /*rAttrList*/,
322 const SvXMLItemMapEntry& /*rEntry*/,
323 const SfxPoolItem& /*rItem*/,
324 const SvXMLUnitConverter& /*rUnitConverter*/,
325 const SvXMLNamespaceMap& /*rNamespaceMap*/,
326 const SfxItemSet* /*pSet*/ /* = NULL */ ) const
328 OSL_FAIL( "special item not handled in xml export" );
331 /** this method is called for every item that has the
332 MID_SW_FLAG_ELEMENT_EXPORT flag set */
333 void SvXMLExportItemMapper::handleElementItem(
334 const SvXMLItemMapEntry& /*rEntry*/,
335 const SfxPoolItem& /*rItem*/ ) const
337 OSL_FAIL( "element item not handled in xml export" );
340 static bool lcl_isOdfDoubleLine( const SvxBorderLine* pLine )
342 bool bIsOdfDouble = false;
343 switch (pLine->GetBorderLineStyle())
345 case SvxBorderLineStyle::DOUBLE:
346 case SvxBorderLineStyle::THINTHICK_SMALLGAP:
347 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
348 case SvxBorderLineStyle::THINTHICK_LARGEGAP:
349 case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
350 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
351 case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
352 bIsOdfDouble = true;
353 break;
354 default:
355 break;
357 return bIsOdfDouble;
360 bool SvXMLExportItemMapper::QueryXMLValue(
361 const SfxPoolItem& rItem,
362 OUString& rValue,
363 sal_uInt16 nMemberId,
364 const SvXMLUnitConverter& rUnitConverter )
366 bool bOk = false;
367 OUStringBuffer aOut;
369 switch ( rItem.Which() )
371 case RES_MARGIN_FIRSTLINE:
372 case RES_MARGIN_TEXTLEFT:
373 case RES_MARGIN_RIGHT:
374 assert(false); // is only called for frame formats?
375 break;
377 case RES_LR_SPACE:
379 const SvxLRSpaceItem& rLRSpace = dynamic_cast<const SvxLRSpaceItem&>(rItem);
381 bOk = true;
382 switch( nMemberId )
384 case MID_L_MARGIN:
385 if (rLRSpace.GetPropLeft() != 100)
387 ::sax::Converter::convertPercent(
388 aOut, rLRSpace.GetPropLeft() );
390 else
392 rUnitConverter.convertMeasureToXML(
393 aOut, rLRSpace.GetLeft() );
395 break;
397 case MID_R_MARGIN:
398 if (rLRSpace.GetPropRight() != 100)
400 ::sax::Converter::convertPercent(
401 aOut, rLRSpace.GetPropRight() );
403 else
405 rUnitConverter.convertMeasureToXML(
406 aOut, rLRSpace.GetRight() );
408 break;
410 case MID_FIRST_AUTO:
411 if (rLRSpace.IsAutoFirst())
413 ::sax::Converter::convertBool(
414 aOut, rLRSpace.IsAutoFirst() );
416 else
417 bOk = false;
418 break;
420 case MID_FIRST_LINE_INDENT:
421 if (!rLRSpace.IsAutoFirst())
423 if (rLRSpace.GetPropTextFirstLineOffset() != 100)
425 ::sax::Converter::convertPercent(
426 aOut, rLRSpace.GetPropTextFirstLineOffset() );
428 else
430 rUnitConverter.convertMeasureToXML(
431 aOut, rLRSpace.GetTextFirstLineOffset() );
434 else
435 bOk = false;
436 break;
438 default:
439 OSL_FAIL( "unknown member id!");
440 bOk = false;
441 break;
444 break;
446 case RES_UL_SPACE:
448 const SvxULSpaceItem& rULSpace = dynamic_cast<const SvxULSpaceItem&>(rItem);
450 switch( nMemberId )
452 case MID_UP_MARGIN:
453 if (rULSpace.GetPropUpper() != 100)
455 ::sax::Converter::convertPercent(
456 aOut, rULSpace.GetPropUpper() );
458 else
460 rUnitConverter.convertMeasureToXML(
461 aOut, rULSpace.GetUpper() );
463 break;
465 case MID_LO_MARGIN:
466 if (rULSpace.GetPropLower() != 100)
468 ::sax::Converter::convertPercent(
469 aOut, rULSpace.GetPropLower() );
471 else
473 rUnitConverter.convertMeasureToXML(
474 aOut, rULSpace.GetLower() );
476 break;
478 default:
479 OSL_FAIL("unknown MemberId");
482 bOk = true;
484 break;
486 case RES_SHADOW:
488 const SvxShadowItem* pShadow = dynamic_cast<const SvxShadowItem*>( &rItem );
489 assert(pShadow && "Wrong Which-ID");
490 if (pShadow)
492 sal_Int32 nX = 1, nY = 1;
493 switch( pShadow->GetLocation() )
495 case SvxShadowLocation::TopLeft:
496 nX = -1;
497 nY = -1;
498 break;
499 case SvxShadowLocation::TopRight:
500 nY = -1;
501 break;
502 case SvxShadowLocation::BottomLeft:
503 nX = -1;
504 break;
505 case SvxShadowLocation::BottomRight:
506 break;
507 case SvxShadowLocation::NONE:
508 default:
509 rValue = GetXMLToken(XML_NONE);
510 return true;
513 nX *= pShadow->GetWidth();
514 nY *= pShadow->GetWidth();
516 ::sax::Converter::convertColor(aOut, pShadow->GetColor());
517 aOut.append( ' ' );
518 rUnitConverter.convertMeasureToXML( aOut, nX );
519 aOut.append( ' ' );
520 rUnitConverter.convertMeasureToXML( aOut, nY );
522 bOk = true;
525 break;
527 case RES_BOX:
529 const SvxBoxItem* pBox = dynamic_cast<const SvxBoxItem*>( &rItem );
530 assert(pBox && "Wrong Which-ID");
531 if (pBox)
534 xml -> MemberId
536 border-padding ALL_BORDER_PADDING
537 border-padding-before LEFT_BORDER_PADDING
538 border-padding-after RIGHT_BORDER_PADDING
539 border-padding-start TOP_BORDER_PADDING
540 border-padding-end BOTTOM_BORDER_PADDING
542 border ALL_BORDER
543 border-before LEFT_BORDER
544 border-after RIGHT_BORDER
545 border-start TOP_BORDER
546 border-end BOTTOM_BORDER
548 border-line-width ALL_BORDER_LINE_WIDTH
549 border-line-width-before LEFT_BORDER_LINE_WIDTH
550 border-line-width-after RIGHT_BORDER_LINE_WIDTH
551 border-line-width-start TOP_BORDER_LINE_WIDTH
552 border-line-width-end BOTTOM_BORDER_LINE_WIDTH
555 const SvxBorderLine* pLeft = pBox->GetLeft();
556 const SvxBorderLine* pRight = pBox->GetRight();
557 const SvxBorderLine* pTop = pBox->GetTop();
558 const SvxBorderLine* pBottom = pBox->GetBottom();
559 const sal_uInt16 nTopDist = pBox->GetDistance( SvxBoxItemLine::TOP );
560 const sal_uInt16 nBottomDist = pBox->GetDistance( SvxBoxItemLine::BOTTOM );
561 const sal_uInt16 nLeftDist = pBox->GetDistance( SvxBoxItemLine::LEFT );
562 const sal_uInt16 nRightDist = pBox->GetDistance( SvxBoxItemLine::RIGHT );
564 // check if we need to export it
565 switch( nMemberId )
567 case ALL_BORDER_PADDING:
568 case LEFT_BORDER_PADDING:
569 case RIGHT_BORDER_PADDING:
570 case TOP_BORDER_PADDING:
571 case BOTTOM_BORDER_PADDING:
573 bool bEqual = nLeftDist == nRightDist &&
574 nLeftDist == nTopDist &&
575 nLeftDist == nBottomDist;
576 // don't export individual paddings if all paddings are equal and
577 // don't export all padding if some paddings are not equal
578 if( (bEqual && ALL_BORDER_PADDING != nMemberId) ||
579 (!bEqual && ALL_BORDER_PADDING == nMemberId) )
580 return false;
582 break;
583 case ALL_BORDER:
584 case LEFT_BORDER:
585 case RIGHT_BORDER:
586 case TOP_BORDER:
587 case BOTTOM_BORDER:
589 bool bEqual = ( nullptr == pTop && nullptr == pBottom &&
590 nullptr == pLeft && nullptr == pRight ) ||
591 ( pTop && pBottom && pLeft && pRight &&
592 *pTop == *pBottom && *pTop == *pLeft &&
593 *pTop == *pRight );
595 // don't export individual borders if all are the same and
596 // don't export all borders if some are not equal
597 if( (bEqual && ALL_BORDER != nMemberId) ||
598 (!bEqual && ALL_BORDER == nMemberId) )
599 return false;
601 break;
602 case ALL_BORDER_LINE_WIDTH:
603 case LEFT_BORDER_LINE_WIDTH:
604 case RIGHT_BORDER_LINE_WIDTH:
605 case TOP_BORDER_LINE_WIDTH:
606 case BOTTOM_BORDER_LINE_WIDTH:
608 // if no line is set, there is nothing to export
609 if( !pTop && !pBottom && !pLeft && !pRight )
610 return false;
612 bool bEqual = nullptr != pTop &&
613 nullptr != pBottom &&
614 nullptr != pLeft &&
615 nullptr != pRight;
617 if( bEqual )
619 const sal_uInt16 nDistance = pTop->GetDistance();
620 const sal_uInt16 nInWidth = pTop->GetInWidth();
621 const sal_uInt16 nOutWidth = pTop->GetOutWidth();
622 const tools::Long nWidth = pTop->GetWidth();
624 bEqual = nDistance == pLeft->GetDistance() &&
625 nInWidth == pLeft->GetInWidth() &&
626 nOutWidth == pLeft->GetOutWidth() &&
627 nWidth == pLeft->GetWidth() &&
628 nDistance == pRight->GetDistance() &&
629 nInWidth == pRight->GetInWidth() &&
630 nOutWidth == pRight->GetOutWidth() &&
631 nWidth == pRight->GetWidth() &&
632 nDistance == pBottom->GetDistance() &&
633 nInWidth == pBottom->GetInWidth() &&
634 nOutWidth == pBottom->GetOutWidth() &&
635 nWidth == pBottom->GetWidth();
638 switch( nMemberId )
640 case ALL_BORDER_LINE_WIDTH:
641 if( !bEqual || pTop->GetDistance() == 0 ||
642 !lcl_isOdfDoubleLine( pTop ) )
643 return false;
644 break;
645 case LEFT_BORDER_LINE_WIDTH:
646 if( bEqual || nullptr == pLeft ||
647 0 == pLeft->GetDistance() ||
648 !lcl_isOdfDoubleLine( pLeft ) )
649 return false;
650 break;
651 case RIGHT_BORDER_LINE_WIDTH:
652 if( bEqual || nullptr == pRight ||
653 0 == pRight->GetDistance() ||
654 !lcl_isOdfDoubleLine( pRight ) )
655 return false;
656 break;
657 case TOP_BORDER_LINE_WIDTH:
658 if( bEqual || nullptr == pTop ||
659 0 == pTop->GetDistance() ||
660 !lcl_isOdfDoubleLine( pTop ) )
661 return false;
662 break;
663 case BOTTOM_BORDER_LINE_WIDTH:
664 if( bEqual || nullptr == pBottom ||
665 0 == pBottom->GetDistance() ||
666 !lcl_isOdfDoubleLine( pBottom ) )
667 return false;
668 break;
671 break;
674 // now export it export
675 switch( nMemberId )
677 // padding
678 case ALL_BORDER_PADDING:
679 case LEFT_BORDER_PADDING:
680 rUnitConverter.convertMeasureToXML( aOut, nLeftDist );
681 break;
682 case RIGHT_BORDER_PADDING:
683 rUnitConverter.convertMeasureToXML( aOut, nRightDist );
684 break;
685 case TOP_BORDER_PADDING:
686 rUnitConverter.convertMeasureToXML( aOut, nTopDist );
687 break;
688 case BOTTOM_BORDER_PADDING:
689 rUnitConverter.convertMeasureToXML( aOut, nBottomDist );
690 break;
692 // border
693 case ALL_BORDER:
694 case LEFT_BORDER:
695 case RIGHT_BORDER:
696 case TOP_BORDER:
697 case BOTTOM_BORDER:
699 const SvxBorderLine* pLine;
700 switch( nMemberId )
702 case ALL_BORDER:
703 case LEFT_BORDER:
704 pLine = pLeft;
705 break;
706 case RIGHT_BORDER:
707 pLine = pRight;
708 break;
709 case TOP_BORDER:
710 pLine = pTop;
711 break;
712 case BOTTOM_BORDER:
713 pLine = pBottom;
714 break;
715 default:
716 pLine = nullptr;
717 break;
720 if( nullptr != pLine )
722 sal_Int32 nWidth = pLine->GetWidth();
724 enum XMLTokenEnum eStyle = XML_SOLID;
725 bool bNoBorder = false;
726 switch (pLine->GetBorderLineStyle())
728 case SvxBorderLineStyle::SOLID:
729 eStyle = XML_SOLID;
730 break;
731 case SvxBorderLineStyle::DOTTED:
732 eStyle = XML_DOTTED;
733 break;
734 case SvxBorderLineStyle::DASHED:
735 eStyle = XML_DASHED;
736 break;
737 case SvxBorderLineStyle::FINE_DASHED:
738 eStyle = XML_FINE_DASHED;
739 break;
740 case SvxBorderLineStyle::DASH_DOT:
741 eStyle = XML_DASH_DOT;
742 break;
743 case SvxBorderLineStyle::DASH_DOT_DOT:
744 eStyle = XML_DASH_DOT_DOT;
745 break;
746 case SvxBorderLineStyle::DOUBLE_THIN:
747 eStyle = XML_DOUBLE_THIN;
748 break;
749 case SvxBorderLineStyle::DOUBLE:
750 case SvxBorderLineStyle::THINTHICK_SMALLGAP:
751 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
752 case SvxBorderLineStyle::THINTHICK_LARGEGAP:
753 case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
754 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
755 case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
756 eStyle = XML_DOUBLE;
757 break;
758 case SvxBorderLineStyle::EMBOSSED:
759 eStyle = XML_RIDGE;
760 break;
761 case SvxBorderLineStyle::ENGRAVED:
762 eStyle = XML_GROOVE;
763 break;
764 case SvxBorderLineStyle::INSET:
765 eStyle = XML_INSET;
766 break;
767 case SvxBorderLineStyle::OUTSET:
768 eStyle = XML_OUTSET;
769 break;
770 default:
771 bNoBorder = true;
774 if ( !bNoBorder )
776 ::sax::Converter::convertMeasure(aOut, nWidth,
777 util::MeasureUnit::TWIP,
778 util::MeasureUnit::POINT);
779 aOut.append( " "
780 + GetXMLToken( eStyle )
781 + " " );
782 ::sax::Converter::convertColor(aOut,
783 pLine->GetColor());
786 else
788 aOut.append( GetXMLToken(XML_NONE) );
791 break;
793 // width
794 case ALL_BORDER_LINE_WIDTH:
795 case LEFT_BORDER_LINE_WIDTH:
796 case RIGHT_BORDER_LINE_WIDTH:
797 case TOP_BORDER_LINE_WIDTH:
798 case BOTTOM_BORDER_LINE_WIDTH:
799 const SvxBorderLine* pLine;
800 switch( nMemberId )
802 case ALL_BORDER_LINE_WIDTH:
803 case LEFT_BORDER_LINE_WIDTH:
804 pLine = pLeft;
805 break;
806 case RIGHT_BORDER_LINE_WIDTH:
807 pLine = pRight;
808 break;
809 case TOP_BORDER_LINE_WIDTH:
810 pLine = pTop;
811 break;
812 case BOTTOM_BORDER_LINE_WIDTH:
813 pLine = pBottom;
814 break;
815 default:
816 return false;
818 rUnitConverter.convertMeasureToXML( aOut, pLine->GetInWidth() );
819 aOut.append( ' ' );
820 rUnitConverter.convertMeasureToXML( aOut, pLine->GetDistance() );
821 aOut.append( ' ' );
822 rUnitConverter.convertMeasureToXML( aOut, pLine->GetOutWidth() );
823 break;
825 bOk = true;
828 break;
830 case RES_BREAK:
832 const SvxFormatBreakItem& rFormatBreak = dynamic_cast<const SvxFormatBreakItem&>(rItem);
834 sal_uInt16 eEnum = 0;
836 switch( nMemberId )
838 case MID_BREAK_BEFORE:
839 switch (rFormatBreak.GetBreak())
841 case SvxBreak::ColumnBefore:
842 eEnum = 1;
843 break;
844 case SvxBreak::PageBefore:
845 eEnum = 2;
846 break;
847 case SvxBreak::NONE:
848 eEnum = 0;
849 break;
850 default:
851 return false;
853 break;
854 case MID_BREAK_AFTER:
855 switch (rFormatBreak.GetBreak())
857 case SvxBreak::ColumnAfter:
858 eEnum = 1;
859 break;
860 case SvxBreak::PageAfter:
861 eEnum = 2;
862 break;
863 case SvxBreak::NONE:
864 eEnum = 0;
865 break;
866 default:
867 return false;
869 break;
872 bOk = SvXMLUnitConverter::convertEnum( aOut, eEnum, psXML_BreakType );
874 break;
876 case RES_KEEP:
878 const SvxFormatKeepItem* pFormatKeep = dynamic_cast<const SvxFormatKeepItem*>( &rItem );
879 assert(pFormatKeep && "Wrong Which-ID");
880 if (pFormatKeep)
882 aOut.append( pFormatKeep->GetValue()
883 ? GetXMLToken( XML_ALWAYS )
884 : GetXMLToken( XML_AUTO ) );
885 bOk = true;
888 break;
890 case RES_PRINT:
892 const SvxPrintItem* pHasTextChangesOnly = dynamic_cast<const SvxPrintItem*>( &rItem );
893 if (pHasTextChangesOnly && !pHasTextChangesOnly->GetValue())
895 aOut.append( "false" );
896 bOk = true;
899 break;
901 case RES_BACKGROUND:
903 const SvxBrushItem& rBrush = dynamic_cast<const SvxBrushItem&>(rItem);
905 // note: the graphic is only exported if nMemberId equals
906 // MID_GRAPHIC...
907 // If not, only the color or transparency is exported
909 switch( nMemberId )
911 case MID_BACK_COLOR:
912 if ( rBrush.GetColor().IsTransparent() )
913 aOut.append( GetXMLToken(XML_TRANSPARENT) );
914 else
916 ::sax::Converter::convertColor(aOut,
917 rBrush.GetColor());
919 bOk = true;
920 break;
922 case MID_GRAPHIC_POSITION:
923 switch (rBrush.GetGraphicPos())
925 case GPOS_LT:
926 case GPOS_MT:
927 case GPOS_RT:
928 aOut.append( GetXMLToken(XML_TOP) );
929 bOk = true;
930 break;
931 case GPOS_LM:
932 case GPOS_MM:
933 case GPOS_RM:
934 aOut.append( GetXMLToken(XML_CENTER) );
935 bOk = true;
936 break;
937 case GPOS_LB:
938 case GPOS_MB:
939 case GPOS_RB:
940 aOut.append( GetXMLToken(XML_BOTTOM) );
941 bOk = true;
942 break;
943 default:
947 if( bOk )
949 aOut.append( ' ' );
951 switch (rBrush.GetGraphicPos())
953 case GPOS_LT:
954 case GPOS_LB:
955 case GPOS_LM:
956 aOut.append( GetXMLToken(XML_LEFT) );
957 break;
958 case GPOS_MT:
959 case GPOS_MM:
960 case GPOS_MB:
961 aOut.append( GetXMLToken(XML_CENTER) );
962 break;
963 case GPOS_RM:
964 case GPOS_RT:
965 case GPOS_RB:
966 aOut.append( GetXMLToken(XML_RIGHT) );
967 break;
968 default:
972 break;
974 case MID_GRAPHIC_REPEAT:
976 SvxGraphicPosition eGraphicPos = rBrush.GetGraphicPos();
977 if( GPOS_AREA == eGraphicPos )
979 aOut.append( GetXMLToken(XML_STRETCH) );
980 bOk = true;
982 else if( GPOS_NONE != eGraphicPos && GPOS_TILED != eGraphicPos )
984 aOut.append( GetXMLToken(XML_BACKGROUND_NO_REPEAT) );
985 bOk = true;
988 break;
990 case MID_GRAPHIC_FILTER:
991 if (rBrush.GetGraphicPos() != GPOS_NONE &&
992 !rBrush.GetGraphicFilter().isEmpty())
994 aOut.append(rBrush.GetGraphicFilter());
995 bOk = true;
997 break;
1000 break;
1002 case RES_PAGEDESC:
1004 const SwFormatPageDesc& rPageDesc = dynamic_cast<const SwFormatPageDesc&>(rItem);
1006 if( MID_PAGEDESC_PAGENUMOFFSET==nMemberId )
1008 ::std::optional<sal_uInt16> oNumOffset = rPageDesc.GetNumOffset();
1009 if (oNumOffset && *oNumOffset > 0)
1011 // #i114163# positiveInteger only!
1012 sal_Int32 const number(*oNumOffset);
1013 aOut.append(number);
1015 else
1017 aOut.append(GetXMLToken(XML_AUTO));
1019 bOk = true;
1022 break;
1024 case RES_LAYOUT_SPLIT:
1025 case RES_ROW_SPLIT:
1027 const SfxBoolItem* pSplit = dynamic_cast<const SfxBoolItem*>( &rItem );
1028 assert(pSplit && "Wrong Which-ID");
1029 if (pSplit)
1031 ::sax::Converter::convertBool( aOut, pSplit->GetValue() );
1032 bOk = true;
1035 break;
1037 case RES_HORI_ORIENT:
1039 const SwFormatHoriOrient* pHoriOrient = dynamic_cast<const SwFormatHoriOrient*>( &rItem );
1040 assert(pHoriOrient && "Wrong Which-ID");
1041 if (pHoriOrient)
1043 SvXMLUnitConverter::convertEnum( aOut, pHoriOrient->GetHoriOrient(),
1044 aXMLTableAlignMap );
1045 bOk = true;
1048 break;
1050 case RES_VERT_ORIENT:
1052 const SwFormatVertOrient* pVertOrient = dynamic_cast<const SwFormatVertOrient*>( &rItem );
1053 assert(pVertOrient && "Wrong Which-ID");
1055 SvXMLUnitConverter::convertEnum( aOut, pVertOrient->GetVertOrient(),
1056 aXMLTableVAlignMap );
1057 bOk = true;
1059 break;
1061 case RES_FRM_SIZE:
1063 const SwFormatFrameSize& rFrameSize = dynamic_cast<const SwFormatFrameSize&>(rItem);
1065 bool bOutHeight = false;
1066 switch( nMemberId )
1068 case MID_FRMSIZE_REL_WIDTH:
1069 if (rFrameSize.GetWidthPercent())
1071 ::sax::Converter::convertPercent(
1072 aOut, rFrameSize.GetWidthPercent() );
1073 bOk = true;
1075 break;
1076 case MID_FRMSIZE_MIN_HEIGHT:
1077 if( SwFrameSize::Minimum == rFrameSize.GetHeightSizeType() )
1078 bOutHeight = true;
1079 break;
1080 case MID_FRMSIZE_FIX_HEIGHT:
1081 if( SwFrameSize::Fixed == rFrameSize.GetHeightSizeType() )
1082 bOutHeight = true;
1083 break;
1086 if( bOutHeight )
1088 rUnitConverter.convertMeasureToXML(aOut, rFrameSize.GetHeight());
1089 bOk = true;
1092 break;
1094 case RES_FRAMEDIR:
1096 Any aAny;
1097 bOk = rItem.QueryValue( aAny );
1098 if( bOk )
1100 std::unique_ptr<XMLPropertyHandler> pWritingModeHandler =
1101 XMLPropertyHandlerFactory::CreatePropertyHandler(
1102 XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT );
1103 OUString sValue;
1104 bOk = pWritingModeHandler->exportXML( sValue, aAny,
1105 rUnitConverter );
1106 if( bOk )
1107 aOut.append( sValue );
1110 break;
1112 case RES_COLLAPSING_BORDERS:
1114 const SfxBoolItem* pBorders = dynamic_cast<const SfxBoolItem*>( &rItem );
1115 assert(pBorders && "Wrong RES-ID");
1116 if (pBorders)
1118 aOut.append( pBorders->GetValue()
1119 ? GetXMLToken( XML_COLLAPSING )
1120 : GetXMLToken( XML_SEPARATING ) );
1121 bOk = true;
1124 break;
1126 default:
1127 OSL_FAIL("GetXMLValue not implemented for this item.");
1128 break;
1131 if ( bOk )
1132 rValue = aOut.makeStringAndClear();
1134 return bOk;
1137 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */