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 .
22 #include "xmlithlp.hxx"
23 #include <sax/tools/converter.hxx>
24 #include <editeng/borderline.hxx>
25 #include <editeng/brushitem.hxx>
27 #include <xmloff/xmluconv.hxx>
28 #include <osl/diagnose.h>
29 #include <o3tl/safeint.hxx>
31 #include <com/sun/star/table/BorderLineStyle.hpp>
32 #include <com/sun/star/text/HoriOrientation.hpp>
33 #include <com/sun/star/text/VertOrientation.hpp>
35 using ::editeng::SvxBorderLine
;
36 using namespace ::xmloff::token
;
37 using namespace ::com::sun::star
;
39 #define SVX_XML_BORDER_WIDTH_THIN 0
40 #define SVX_XML_BORDER_WIDTH_MIDDLE 1
41 #define SVX_XML_BORDER_WIDTH_THICK 2
43 const struct SvXMLEnumMapEntry
<sal_uInt16
> psXML_BorderStyles
[] =
45 { XML_NONE
, table::BorderLineStyle::NONE
},
46 { XML_HIDDEN
, table::BorderLineStyle::NONE
},
47 { XML_SOLID
, table::BorderLineStyle::SOLID
},
48 { XML_DOUBLE
, table::BorderLineStyle::DOUBLE
},
49 { XML_DOUBLE_THIN
, table::BorderLineStyle::DOUBLE_THIN
},
50 { XML_DOTTED
, table::BorderLineStyle::DOTTED
},
51 { XML_DASHED
, table::BorderLineStyle::DASHED
},
52 { XML_FINE_DASHED
, table::BorderLineStyle::FINE_DASHED
},
53 { XML_DASH_DOT
, table::BorderLineStyle::DASH_DOT
},
54 { XML_DASH_DOT_DOT
, table::BorderLineStyle::DASH_DOT_DOT
},
55 { XML_GROOVE
, table::BorderLineStyle::ENGRAVED
},
56 { XML_RIDGE
, table::BorderLineStyle::EMBOSSED
},
57 { XML_INSET
, table::BorderLineStyle::INSET
},
58 { XML_OUTSET
, table::BorderLineStyle::OUTSET
},
59 { XML_TOKEN_INVALID
, 0 }
62 const struct SvXMLEnumMapEntry
<sal_uInt16
> psXML_NamedBorderWidths
[] =
64 { XML_THIN
, SVX_XML_BORDER_WIDTH_THIN
},
65 { XML_MIDDLE
, SVX_XML_BORDER_WIDTH_MIDDLE
},
66 { XML_THICK
, SVX_XML_BORDER_WIDTH_THICK
},
67 { XML_TOKEN_INVALID
, 0 }
69 // mapping tables to map external xml input to internal box line widths
71 const sal_uInt16 aBorderWidths
[] = {
72 SvxBorderLineWidth::Hairline
,
73 SvxBorderLineWidth::VeryThin
,
74 SvxBorderLineWidth::Thin
77 bool sw_frmitems_parseXMLBorder( std::u16string_view rValue
,
78 const SvXMLUnitConverter
& rUnitConverter
,
79 bool& rHasStyle
, sal_uInt16
& rStyle
,
80 bool& rHasWidth
, sal_uInt16
& rWidth
,
81 sal_uInt16
& rNamedWidth
,
82 bool& rHasColor
, Color
& rColor
)
84 std::u16string_view aToken
;
85 SvXMLTokenEnumerator
aTokens( rValue
);
93 rNamedWidth
= USHRT_MAX
;
96 while( aTokens
.getNextToken( aToken
) && !aToken
.empty() )
99 SvXMLUnitConverter::convertEnum( rNamedWidth
, aToken
,
100 psXML_NamedBorderWidths
) )
104 else if( !rHasStyle
&&
105 SvXMLUnitConverter::convertEnum( rStyle
, aToken
,
106 psXML_BorderStyles
) )
110 else if (!rHasColor
&& ::sax::Converter::convertColor(rColor
, aToken
))
114 else if( !rHasWidth
&&
115 rUnitConverter
.convertMeasureToCore(nTemp
, aToken
, 0, USHRT_MAX
))
117 rWidth
= o3tl::narrowing
<sal_uInt16
>(nTemp
);
127 return rHasStyle
|| rHasWidth
|| rHasColor
;
130 static void sw_frmitems_setXMLBorderStyle( SvxBorderLine
& rLine
, sal_uInt16 nStyle
)
132 SvxBorderLineStyle eStyle
= SvxBorderLineStyle::NONE
;
133 if ( nStyle
!= table::BorderLineStyle::NONE
)
134 eStyle
= SvxBorderLineStyle( nStyle
);
135 rLine
.SetBorderLineStyle(eStyle
);
138 bool sw_frmitems_setXMLBorder( std::unique_ptr
<SvxBorderLine
>& rpLine
,
139 bool bHasStyle
, sal_uInt16 nStyle
,
140 bool bHasWidth
, sal_uInt16 nWidth
,
141 sal_uInt16 nNamedWidth
,
142 bool bHasColor
, const Color
& rColor
)
144 // first of all, delete an empty line
145 if( (bHasStyle
&& table::BorderLineStyle::NONE
== nStyle
) ||
146 (bHasWidth
&& USHRT_MAX
== nNamedWidth
&& 0 == nWidth
) )
148 bool bRet
= nullptr != rpLine
;
153 // if there is no line and no style and no with, there will never be a line
154 if( !rpLine
&& !(bHasStyle
&& bHasWidth
) )
157 // We now do know that there will be a line
159 rpLine
.reset(new SvxBorderLine
);
162 (USHRT_MAX
!= nNamedWidth
|| (nWidth
!= rpLine
->GetWidth() ) ) ) ||
164 ((table::BorderLineStyle::SOLID
== nStyle
&& rpLine
->GetDistance()) ||
165 (table::BorderLineStyle::DOUBLE
== nStyle
&& !rpLine
->GetDistance())) ) )
167 bool bDouble
= (bHasWidth
&& table::BorderLineStyle::DOUBLE
== nStyle
) ||
168 rpLine
->GetDistance();
170 // fdo#38542: for double borders, do not override the width
171 // set via style:border-line-width{,-left,-right,-top,-bottom}
172 if (!bDouble
|| !rpLine
->GetWidth())
174 // The width has to be changed
175 if (bHasWidth
&& USHRT_MAX
!= nNamedWidth
)
179 rpLine
->SetBorderLineStyle( SvxBorderLineStyle::DOUBLE
);
181 rpLine
->SetWidth( aBorderWidths
[nNamedWidth
] );
186 nWidth
= rpLine
->GetScaledWidth();
188 rpLine
->SetWidth( nWidth
);
191 sw_frmitems_setXMLBorderStyle( *rpLine
, nStyle
);
196 rpLine
->SetColor( rColor
);
201 void sw_frmitems_setXMLBorder( std::unique_ptr
<SvxBorderLine
>& rpLine
,
202 sal_uInt16 nWidth
, sal_uInt16 nOutWidth
,
203 sal_uInt16 nInWidth
, sal_uInt16 nDistance
)
206 rpLine
.reset(new SvxBorderLine
);
209 rpLine
->SetWidth( nWidth
);
211 rpLine
->GuessLinesWidths(SvxBorderLineStyle::DOUBLE
,
212 nOutWidth
, nInWidth
, nDistance
);
215 const struct SvXMLEnumMapEntry
<SvxGraphicPosition
> psXML_BrushRepeat
[] =
217 { XML_REPEAT
, GPOS_TILED
},
218 { XML_BACKGROUND_NO_REPEAT
, GPOS_MM
},
219 { XML_STRETCH
, GPOS_AREA
},
220 { XML_TOKEN_INVALID
, SvxGraphicPosition(0) }
223 const struct SvXMLEnumMapEntry
<SvxGraphicPosition
> psXML_BrushHoriPos
[] =
225 { XML_LEFT
, GPOS_LM
},
226 { XML_RIGHT
, GPOS_RM
},
227 { XML_TOKEN_INVALID
, SvxGraphicPosition(0) }
230 const struct SvXMLEnumMapEntry
<SvxGraphicPosition
> psXML_BrushVertPos
[] =
232 { XML_TOP
, GPOS_MT
},
233 { XML_BOTTOM
, GPOS_MB
},
234 { XML_TOKEN_INVALID
, SvxGraphicPosition(0) }
237 void sw_frmitems_MergeXMLHoriPos( SvxGraphicPosition
& ePos
,
238 SvxGraphicPosition eHori
)
240 OSL_ENSURE( GPOS_LM
==eHori
|| GPOS_MM
==eHori
|| GPOS_RM
==eHori
,
241 "sw_frmitems_MergeXMLHoriPos: vertical pos must be middle" );
248 ePos
= GPOS_LM
==eHori
? GPOS_LT
: (GPOS_MM
==eHori
? GPOS_MT
: GPOS_RT
);
260 ePos
= GPOS_LM
==eHori
? GPOS_LB
: (GPOS_MM
==eHori
? GPOS_MB
: GPOS_RB
);
267 void sw_frmitems_MergeXMLVertPos( SvxGraphicPosition
& ePos
,
268 SvxGraphicPosition eVert
)
270 OSL_ENSURE( GPOS_MT
==eVert
|| GPOS_MM
==eVert
|| GPOS_MB
==eVert
,
271 "sw_frmitems_MergeXMLVertPos: horizontal pos must be middle" );
278 ePos
= GPOS_MT
==eVert
? GPOS_LT
: (GPOS_MM
==eVert
? GPOS_LM
: GPOS_LB
);
290 ePos
= GPOS_MT
==eVert
? GPOS_RT
: (GPOS_MM
==eVert
? GPOS_RM
: GPOS_RB
);
297 const struct SvXMLEnumMapEntry
<sal_uInt16
> psXML_BreakType
[] =
302 { XML_EVEN_PAGE
, 2 },
304 { XML_TOKEN_INVALID
, 0}
307 const struct SvXMLEnumMapEntry
<sal_Int16
> aXMLTableAlignMap
[] =
309 { XML_LEFT
, text::HoriOrientation::LEFT
},
310 { XML_LEFT
, text::HoriOrientation::LEFT_AND_WIDTH
},
311 { XML_CENTER
, text::HoriOrientation::CENTER
},
312 { XML_RIGHT
, text::HoriOrientation::RIGHT
},
313 { XML_MARGINS
, text::HoriOrientation::FULL
},
314 { XML_MARGINS
, text::HoriOrientation::NONE
},
315 { XML_TOKEN_INVALID
, 0 }
318 const struct SvXMLEnumMapEntry
<sal_Int16
> aXMLTableVAlignMap
[] =
320 { XML_TOP
, text::VertOrientation::TOP
},
321 { XML_MIDDLE
, text::VertOrientation::CENTER
},
322 { XML_BOTTOM
, text::VertOrientation::BOTTOM
},
323 { XML_TOKEN_INVALID
, 0 }
326 const struct SvXMLEnumMapEntry
<sal_uInt16
> aXML_KeepTogetherType
[] =
330 { XML_TOKEN_INVALID
, 0}
333 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */