LibreOffice Module sw (master)  1
xmlithlp.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 <limits.h>
21 
22 #include "xmlithlp.hxx"
23 #include <sax/tools/converter.hxx>
24 #include <editeng/borderline.hxx>
25 #include <editeng/brushitem.hxx>
26 
27 #include <xmloff/xmluconv.hxx>
28 #include <osl/diagnose.h>
29 #include <o3tl/safeint.hxx>
30 
31 #include <com/sun/star/table/BorderLineStyle.hpp>
32 #include <com/sun/star/text/HoriOrientation.hpp>
33 #include <com/sun/star/text/VertOrientation.hpp>
34 
35 using ::editeng::SvxBorderLine;
36 using namespace ::xmloff::token;
37 using namespace ::com::sun::star;
38 
39 #define SVX_XML_BORDER_WIDTH_THIN 0
40 #define SVX_XML_BORDER_WIDTH_MIDDLE 1
41 #define SVX_XML_BORDER_WIDTH_THICK 2
42 
43 const struct SvXMLEnumMapEntry<sal_uInt16> psXML_BorderStyles[] =
44 {
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 }
60 };
61 
62 const struct SvXMLEnumMapEntry<sal_uInt16> psXML_NamedBorderWidths[] =
63 {
67  { XML_TOKEN_INVALID, 0 }
68 };
69 // mapping tables to map external xml input to internal box line widths
70 
71 const sal_uInt16 aBorderWidths[] =
72 {
76 };
77 
78 bool sw_frmitems_parseXMLBorder( std::u16string_view rValue,
79  const SvXMLUnitConverter& rUnitConverter,
80  bool& rHasStyle, sal_uInt16& rStyle,
81  bool& rHasWidth, sal_uInt16& rWidth,
82  sal_uInt16& rNamedWidth,
83  bool& rHasColor, Color& rColor )
84 {
85  std::u16string_view aToken;
86  SvXMLTokenEnumerator aTokens( rValue );
87 
88  rHasStyle = false;
89  rHasWidth = false;
90  rHasColor = false;
91 
92  rStyle = USHRT_MAX;
93  rWidth = 0;
94  rNamedWidth = USHRT_MAX;
95 
96  sal_Int32 nTemp;
97  while( aTokens.getNextToken( aToken ) && !aToken.empty() )
98  {
99  if( !rHasWidth &&
100  SvXMLUnitConverter::convertEnum( rNamedWidth, aToken,
101  psXML_NamedBorderWidths ) )
102  {
103  rHasWidth = true;
104  }
105  else if( !rHasStyle &&
106  SvXMLUnitConverter::convertEnum( rStyle, aToken,
107  psXML_BorderStyles ) )
108  {
109  rHasStyle = true;
110  }
111  else if (!rHasColor && ::sax::Converter::convertColor(rColor, aToken))
112  {
113  rHasColor = true;
114  }
115  else if( !rHasWidth &&
116  rUnitConverter.convertMeasureToCore(nTemp, aToken, 0, USHRT_MAX))
117  {
118  rWidth = o3tl::narrowing<sal_uInt16>(nTemp);
119  rHasWidth = true;
120  }
121  else
122  {
123  // misformed
124  return false;
125  }
126  }
127 
128  return rHasStyle || rHasWidth || rHasColor;
129 }
130 
131 static void sw_frmitems_setXMLBorderStyle( SvxBorderLine& rLine, sal_uInt16 nStyle )
132 {
133  SvxBorderLineStyle eStyle = SvxBorderLineStyle::NONE;
134  if ( nStyle != table::BorderLineStyle::NONE )
135  eStyle = SvxBorderLineStyle( nStyle );
136  rLine.SetBorderLineStyle(eStyle);
137 }
138 
139 bool sw_frmitems_setXMLBorder( std::unique_ptr<SvxBorderLine>& rpLine,
140  bool bHasStyle, sal_uInt16 nStyle,
141  bool bHasWidth, sal_uInt16 nWidth,
142  sal_uInt16 nNamedWidth,
143  bool bHasColor, const Color& rColor )
144 {
145  // first of all, delete an empty line
146  if( (bHasStyle && table::BorderLineStyle::NONE == nStyle) ||
147  (bHasWidth && USHRT_MAX == nNamedWidth && 0 == nWidth) )
148  {
149  bool bRet = nullptr != rpLine;
150  rpLine.reset();
151  return bRet;
152  }
153 
154  // if there is no line and no style and no with, there will never be a line
155  if( !rpLine && !(bHasStyle && bHasWidth) )
156  return false;
157 
158  // We now do know that there will be a line
159  if( !rpLine )
160  rpLine.reset(new SvxBorderLine);
161 
162  if( ( bHasWidth &&
163  (USHRT_MAX != nNamedWidth || (nWidth != rpLine->GetWidth() ) ) ) ||
164  ( bHasStyle &&
165  ((table::BorderLineStyle::SOLID == nStyle && rpLine->GetDistance()) ||
166  (table::BorderLineStyle::DOUBLE == nStyle && !rpLine->GetDistance())) ) )
167  {
168  bool bDouble = (bHasWidth && table::BorderLineStyle::DOUBLE == nStyle ) ||
169  rpLine->GetDistance();
170 
171  // fdo#38542: for double borders, do not override the width
172  // set via style:border-line-width{,-left,-right,-top,-bottom}
173  if (!bDouble || !rpLine->GetWidth())
174  {
175  // The width has to be changed
176  if (bHasWidth && USHRT_MAX != nNamedWidth)
177  {
178  if (bDouble)
179  {
180  rpLine->SetBorderLineStyle( SvxBorderLineStyle::DOUBLE );
181  }
182  rpLine->SetWidth( aBorderWidths[nNamedWidth] );
183  }
184  else
185  {
186  if (!bHasWidth)
187  nWidth = rpLine->GetScaledWidth();
188 
189  rpLine->SetWidth( nWidth );
190  }
191  }
192  sw_frmitems_setXMLBorderStyle( *rpLine, nStyle );
193  }
194 
195  // set color
196  if( bHasColor )
197  rpLine->SetColor( rColor );
198 
199  return true;
200 }
201 
202 void sw_frmitems_setXMLBorder( std::unique_ptr<SvxBorderLine>& rpLine,
203  sal_uInt16 nWidth, sal_uInt16 nOutWidth,
204  sal_uInt16 nInWidth, sal_uInt16 nDistance )
205 {
206  if( !rpLine )
207  rpLine.reset(new SvxBorderLine);
208 
209  if( nWidth > 0 )
210  rpLine->SetWidth( nWidth );
211  else
212  rpLine->GuessLinesWidths(SvxBorderLineStyle::DOUBLE,
213  nOutWidth, nInWidth, nDistance);
214 }
215 
217 {
218  { XML_REPEAT, GPOS_TILED },
220  { XML_STRETCH, GPOS_AREA },
222 };
223 
225 {
226  { XML_LEFT, GPOS_LM },
227  { XML_RIGHT, GPOS_RM },
229 };
230 
232 {
233  { XML_TOP, GPOS_MT },
234  { XML_BOTTOM, GPOS_MB },
236 };
237 
239  SvxGraphicPosition eHori )
240 {
241  OSL_ENSURE( GPOS_LM==eHori || GPOS_MM==eHori || GPOS_RM==eHori,
242  "sw_frmitems_MergeXMLHoriPos: vertical pos must be middle" );
243 
244  switch( ePos )
245  {
246  case GPOS_LT:
247  case GPOS_MT:
248  case GPOS_RT:
249  ePos = GPOS_LM==eHori ? GPOS_LT : (GPOS_MM==eHori ? GPOS_MT : GPOS_RT);
250  break;
251 
252  case GPOS_LM:
253  case GPOS_MM:
254  case GPOS_RM:
255  ePos = eHori;
256  break;
257 
258  case GPOS_LB:
259  case GPOS_MB:
260  case GPOS_RB:
261  ePos = GPOS_LM==eHori ? GPOS_LB : (GPOS_MM==eHori ? GPOS_MB : GPOS_RB);
262  break;
263  default:
264  ;
265  }
266 }
267 
269  SvxGraphicPosition eVert )
270 {
271  OSL_ENSURE( GPOS_MT==eVert || GPOS_MM==eVert || GPOS_MB==eVert,
272  "sw_frmitems_MergeXMLVertPos: horizontal pos must be middle" );
273 
274  switch( ePos )
275  {
276  case GPOS_LT:
277  case GPOS_LM:
278  case GPOS_LB:
279  ePos = GPOS_MT==eVert ? GPOS_LT : (GPOS_MM==eVert ? GPOS_LM : GPOS_LB);
280  break;
281 
282  case GPOS_MT:
283  case GPOS_MM:
284  case GPOS_MB:
285  ePos = eVert;
286  break;
287 
288  case GPOS_RT:
289  case GPOS_RM:
290  case GPOS_RB:
291  ePos = GPOS_MT==eVert ? GPOS_RT : (GPOS_MM==eVert ? GPOS_RM : GPOS_RB);
292  break;
293  default:
294  ;
295  }
296 }
297 
298 const struct SvXMLEnumMapEntry<sal_uInt16> psXML_BreakType[] =
299 {
300  { XML_AUTO, 0 },
301  { XML_COLUMN, 1 },
302  { XML_PAGE, 2 },
303  { XML_EVEN_PAGE, 2 },
304  { XML_ODD_PAGE, 2 },
305  { XML_TOKEN_INVALID, 0}
306 };
307 
308 const struct SvXMLEnumMapEntry<sal_Int16> aXMLTableAlignMap[] =
309 {
310  { XML_LEFT, text::HoriOrientation::LEFT },
311  { XML_LEFT, text::HoriOrientation::LEFT_AND_WIDTH },
312  { XML_CENTER, text::HoriOrientation::CENTER },
313  { XML_RIGHT, text::HoriOrientation::RIGHT },
314  { XML_MARGINS, text::HoriOrientation::FULL },
316  { XML_TOKEN_INVALID, 0 }
317 };
318 
319 const struct SvXMLEnumMapEntry<sal_Int16> aXMLTableVAlignMap[] =
320 {
321  { XML_TOP, text::VertOrientation::TOP },
322  { XML_MIDDLE, text::VertOrientation::CENTER },
323  { XML_BOTTOM, text::VertOrientation::BOTTOM },
324  { XML_TOKEN_INVALID, 0 }
325 };
326 
327 const struct SvXMLEnumMapEntry<sal_uInt16> aXML_KeepTogetherType[] =
328 {
329  { XML_ALWAYS, 0 },
330  { XML_AUTO, 1 },
331  { XML_TOKEN_INVALID, 0}
332 };
333 
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool convertMeasureToCore(sal_Int32 &rValue, std::u16string_view rString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32) const
XML_LEFT
XML_INSET
GPOS_RM
XML_DASH_DOT_DOT
XML_DASH_DOT
static void sw_frmitems_setXMLBorderStyle(SvxBorderLine &rLine, sal_uInt16 nStyle)
Definition: xmlithlp.cxx:131
void sw_frmitems_MergeXMLHoriPos(SvxGraphicPosition &ePos, SvxGraphicPosition eHori)
Definition: xmlithlp.cxx:238
XML_AUTO
GPOS_LT
#define SVX_XML_BORDER_WIDTH_MIDDLE
Definition: xmlithlp.cxx:40
XML_DOUBLE
XML_SOLID
XML_PAGE
XML_OUTSET
XML_BACKGROUND_NO_REPEAT
const struct SvXMLEnumMapEntry< sal_uInt16 > psXML_BorderStyles[]
Definition: xmlithlp.cxx:43
XML_HIDDEN
XML_DASHED
const struct SvXMLEnumMapEntry< sal_Int16 > aXMLTableVAlignMap[]
Definition: xmlithlp.cxx:319
#define DEF_LINE_WIDTH_1
const struct SvXMLEnumMapEntry< SvxGraphicPosition > psXML_BrushVertPos[]
Definition: xmlithlp.cxx:231
XML_ODD_PAGE
XML_COLUMN
bool sw_frmitems_parseXMLBorder(std::u16string_view rValue, const SvXMLUnitConverter &rUnitConverter, bool &rHasStyle, sal_uInt16 &rStyle, bool &rHasWidth, sal_uInt16 &rWidth, sal_uInt16 &rNamedWidth, bool &rHasColor, Color &rColor)
Define various helper variables and functions for xmlimpit.cxx and xmlexpit.cxx.
Definition: xmlithlp.cxx:78
SvxBorderLineStyle
GPOS_TILED
GPOS_LM
XML_THIN
XML_STRETCH
XML_REPEAT
XML_FINE_DASHED
XML_TOKEN_INVALID
XML_MIDDLE
const struct SvXMLEnumMapEntry< sal_Int16 > aXMLTableAlignMap[]
Definition: xmlithlp.cxx:308
bool getNextToken(std::u16string_view &rToken)
XML_RIDGE
XML_TOP
XML_RIGHT
GPOS_MT
SvxGraphicPosition
static bool convertColor(sal_Int32 &rColor, std::u16string_view rValue)
GPOS_MM
XML_ALWAYS
#define SVX_XML_BORDER_WIDTH_THIN
Definition: xmlithlp.cxx:39
GPOS_AREA
bool sw_frmitems_setXMLBorder(std::unique_ptr< SvxBorderLine > &rpLine, bool bHasStyle, sal_uInt16 nStyle, bool bHasWidth, sal_uInt16 nWidth, sal_uInt16 nNamedWidth, bool bHasColor, const Color &rColor)
Definition: xmlithlp.cxx:139
XML_BOTTOM
GPOS_MB
const struct SvXMLEnumMapEntry< sal_uInt16 > psXML_NamedBorderWidths[]
Definition: xmlithlp.cxx:62
XML_NONE
XML_CENTER
const struct SvXMLEnumMapEntry< SvxGraphicPosition > psXML_BrushHoriPos[]
Definition: xmlithlp.cxx:224
#define SVX_XML_BORDER_WIDTH_THICK
Definition: xmlithlp.cxx:41
static bool convertEnum(EnumT &rEnum, std::u16string_view rValue, const SvXMLEnumMapEntry< EnumT > *pMap)
XML_EVEN_PAGE
void sw_frmitems_MergeXMLVertPos(SvxGraphicPosition &ePos, SvxGraphicPosition eVert)
Definition: xmlithlp.cxx:268
#define DEF_LINE_WIDTH_5
XML_DOUBLE_THIN
const struct SvXMLEnumMapEntry< sal_uInt16 > psXML_BreakType[]
Definition: xmlithlp.cxx:298
XML_THICK
GPOS_RB
#define DEF_LINE_WIDTH_0
GPOS_LB
GPOS_RT
const sal_uInt16 aBorderWidths[]
Definition: xmlithlp.cxx:71
XML_DOTTED
XML_MARGINS
const struct SvXMLEnumMapEntry< sal_uInt16 > aXML_KeepTogetherType[]
Definition: xmlithlp.cxx:327
const struct SvXMLEnumMapEntry< SvxGraphicPosition > psXML_BrushRepeat[]
Definition: xmlithlp.cxx:216
XML_GROOVE