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 <sal/config.h>
22 #include <rtl/math.hxx>
23 #include <svx/framelink.hxx>
25 #include <editeng/borderline.hxx>
26 #include <o3tl/hash_combine.hxx>
29 using namespace ::com::sun::star
;
30 using namespace editeng
;
35 Style::Style( double nP
, double nD
, double nS
, SvxBorderLineStyle nType
, double fScale
)
39 mfPatternScale
= fScale
;
43 Style::Style( const Color
& rColorPrim
, const Color
& rColorSecn
, const Color
& rColorGap
, bool bUseGapColor
, double nP
, double nD
, double nS
, SvxBorderLineStyle nType
, double fScale
)
47 mfPatternScale
= fScale
;
48 Set( rColorPrim
, rColorSecn
, rColorGap
, bUseGapColor
, nP
, nD
, nS
);
51 Style::Style( const editeng::SvxBorderLine
* pBorder
, double fScale
)
54 if(nullptr != pBorder
)
56 mfPatternScale
= fScale
;
57 Set( pBorder
, fScale
);
63 maColorPrim
= Color();
64 maColorSecn
= Color();
66 mbUseGapColor
= false;
67 meRefMode
= RefMode::Centered
;
72 mnType
= SvxBorderLineStyle::SOLID
;
73 mbWordTableCell
= false;
76 void Style::Set( double nP
, double nD
, double nS
)
78 /* nP nD nS -> mfPrim mfDist mfSecn
79 --------------------------------------
85 mfPrim
= rtl::math::round(nP
? nP
: nS
, 2);
86 mfDist
= rtl::math::round((nP
&& nS
) ? nD
: 0, 2);
87 mfSecn
= rtl::math::round((nP
&& nD
) ? nS
: 0, 2);
90 void Style::Set( const Color
& rColorPrim
, const Color
& rColorSecn
, const Color
& rColorGap
, bool bUseGapColor
, double nP
, double nD
, double nS
)
92 maColorPrim
= rColorPrim
;
93 maColorSecn
= rColorSecn
;
94 maColorGap
= rColorGap
;
95 mbUseGapColor
= bUseGapColor
;
99 void Style::Set( const SvxBorderLine
* pBorder
, double fScale
, sal_uInt16 nMaxWidth
)
101 if(nullptr == pBorder
)
107 maColorPrim
= pBorder
->GetColorOut();
108 maColorSecn
= pBorder
->GetColorIn();
109 maColorGap
= pBorder
->GetColorGap();
110 mbUseGapColor
= pBorder
->HasGapColor();
112 const sal_uInt16
nPrim(pBorder
->GetOutWidth());
113 const sal_uInt16
nDist(pBorder
->GetDistance());
114 const sal_uInt16
nSecn(pBorder
->GetInWidth());
116 mnType
= pBorder
->GetBorderLineStyle();
117 mfPatternScale
= fScale
;
119 if( !nSecn
) // no or single frame border
121 Set( std::min
<double>(nPrim
* fScale
, nMaxWidth
), 0, 0 );
125 Set(std::min
<double>(nPrim
* fScale
, nMaxWidth
), std::min
<double>(nDist
* fScale
, nMaxWidth
), std::min
<double>(nSecn
* fScale
, nMaxWidth
));
126 // Enlarge the style if distance is too small due to rounding losses.
127 double nPixWidth
= std::min
<double>((nPrim
+ nDist
+ nSecn
) * fScale
, nMaxWidth
);
129 if( nPixWidth
> GetWidth() )
131 mfDist
= nPixWidth
- mfPrim
- mfSecn
;
134 // Shrink the style if it is too thick for the control.
135 while( GetWidth() > nMaxWidth
)
137 // First decrease space between lines.
144 // Still too thick? Decrease the line widths.
145 if (mfPrim
!= 0.0 && rtl::math::approxEqual(mfPrim
, mfSecn
))
147 // Both lines equal - decrease both to keep symmetry.
153 // Decrease each line for itself
157 if ((GetWidth() > nMaxWidth
) && mfSecn
!= 0.0)
163 void Style::MirrorSelf()
167 std::swap( mfPrim
, mfSecn
);
168 // also need to swap colors
169 std::swap( maColorPrim
, maColorSecn
);
172 if( meRefMode
!= RefMode::Centered
)
174 meRefMode
= (meRefMode
== RefMode::Begin
) ? RefMode::End
: RefMode::Begin
;
178 bool Style::operator==( const Style
& rOther
) const
181 // ptr compare (same instance)
184 return (Prim() == rOther
.Prim()
185 && Dist() == rOther
.Dist()
186 && Secn() == rOther
.Secn()
187 && GetColorPrim() == rOther
.GetColorPrim()
188 && GetColorSecn() == rOther
.GetColorSecn()
189 && GetColorGap() == rOther
.GetColorGap()
190 && GetRefMode() == rOther
.GetRefMode()
191 && UseGapColor() == rOther
.UseGapColor()
192 && Type() == rOther
.Type());
195 size_t Style::hashCode() const
197 std::size_t seed
= 0;
198 o3tl::hash_combine(seed
, Prim());
199 o3tl::hash_combine(seed
, Dist());
200 o3tl::hash_combine(seed
, Secn());
201 o3tl::hash_combine(seed
, static_cast<sal_Int32
>(GetColorPrim()));
202 o3tl::hash_combine(seed
, static_cast<sal_Int32
>(GetColorSecn()));
203 o3tl::hash_combine(seed
, static_cast<sal_Int32
>(GetColorGap()));
204 o3tl::hash_combine(seed
, GetRefMode());
205 o3tl::hash_combine(seed
, UseGapColor());
206 o3tl::hash_combine(seed
, Type());
214 * Gets the weight of rStyle, according to [MS-OI29500] v20171130, 2.1.168 Part 1 Section 17.4.66,
215 * tcBorders (Table Cell Borders).
217 double GetWordTableCellBorderWeight(const Style
& rStyle
)
219 double fWidth
= rStyle
.GetWidth();
220 int nBorderNumber
= 0;
222 // See lcl_convertBorderStyleFromToken() in writerfilter/ and ConvertBorderStyleFromWord() in
223 // editeng/, this is the opposite of the combination of those functions.
224 switch (rStyle
.Type())
226 case SvxBorderLineStyle::NONE
:
228 case SvxBorderLineStyle::DOTTED
:
229 case SvxBorderLineStyle::DASHED
:
231 case SvxBorderLineStyle::SOLID
:
237 case SvxBorderLineStyle::DOUBLE
:
238 case SvxBorderLineStyle::DOUBLE_THIN
:
242 // dashDotStroked = 23
245 case SvxBorderLineStyle::DASH_DOT
:
249 case SvxBorderLineStyle::DASH_DOT_DOT
:
253 case SvxBorderLineStyle::THINTHICK_SMALLGAP
:
254 // thinThickSmallGap = 11
257 case SvxBorderLineStyle::THICKTHIN_SMALLGAP
:
258 // thickThinSmallGap = 12
259 // thinThickThinSmallGap = 13
262 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP
:
263 // thinThickMediumGap = 14
266 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP
:
267 // thickThinMediumGap = 15
268 // thinThickThinMediumGap = 16
271 case SvxBorderLineStyle::THINTHICK_LARGEGAP
:
272 // thinThickLargeGap = 17
275 case SvxBorderLineStyle::THICKTHIN_LARGEGAP
:
276 // thickThinLargeGap = 18
277 // thinThickThinLargeGap = 19
280 case SvxBorderLineStyle::FINE_DASHED
:
284 case SvxBorderLineStyle::EMBOSSED
:
288 case SvxBorderLineStyle::ENGRAVED
:
289 // threeDEngrave = 25
292 case SvxBorderLineStyle::OUTSET
:
296 case SvxBorderLineStyle::INSET
:
302 return nBorderNumber
* fWidth
;
306 bool Style::operator<( const Style
& rOther
) const
310 // The below code would first compare based on the border width, Word compares based on its
311 // calculated weight, do that in the compat case.
312 double fLW
= GetWordTableCellBorderWeight(*this);
313 double fRW
= GetWordTableCellBorderWeight(rOther
);
314 if (!rtl::math::approxEqual(fLW
, fRW
))
320 // different total widths -> this<rOther, if this is thinner
321 double nLW
= GetWidth();
322 double nRW
= rOther
.GetWidth();
323 if( !rtl::math::approxEqual(nLW
, nRW
) ) return nLW
< nRW
;
325 // one line double, the other single -> this<rOther, if this is single
326 if( (Secn() == 0) != (rOther
.Secn() == 0) ) return Secn() == 0;
328 // both lines double with different distances -> this<rOther, if distance of this greater
329 if( (Secn() && rOther
.Secn()) && !rtl::math::approxEqual(Dist(), rOther
.Dist()) ) return Dist() > rOther
.Dist();
331 // both lines single and 1 unit thick, only one is dotted -> this<rOther, if this is dotted
332 if ((nLW
== 1) && !Secn() && !rOther
.Secn() && (Type() != rOther
.Type())) return Type() > rOther
.Type();
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */