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>
28 using namespace ::com::sun::star
;
29 using namespace editeng
;
34 Style::Style( double nP
, double nD
, double nS
, SvxBorderLineStyle nType
, double fScale
)
38 mfPatternScale
= fScale
;
42 Style::Style( const Color
& rColorPrim
, const Color
& rColorSecn
, const Color
& rColorGap
, bool bUseGapColor
, double nP
, double nD
, double nS
, SvxBorderLineStyle nType
, double fScale
)
46 mfPatternScale
= fScale
;
47 Set( rColorPrim
, rColorSecn
, rColorGap
, bUseGapColor
, nP
, nD
, nS
);
50 Style::Style( const editeng::SvxBorderLine
* pBorder
, double fScale
)
53 if(nullptr != pBorder
)
55 mfPatternScale
= fScale
;
56 Set( pBorder
, fScale
);
62 maColorPrim
= Color();
63 maColorSecn
= Color();
65 mbUseGapColor
= false;
66 meRefMode
= RefMode::Centered
;
71 mnType
= SvxBorderLineStyle::SOLID
;
72 mbWordTableCell
= false;
75 void Style::Set( double nP
, double nD
, double nS
)
77 /* nP nD nS -> mfPrim mfDist mfSecn
78 --------------------------------------
84 mfPrim
= rtl::math::round(nP
? nP
: nS
, 2);
85 mfDist
= rtl::math::round((nP
&& nS
) ? nD
: 0, 2);
86 mfSecn
= rtl::math::round((nP
&& nD
) ? nS
: 0, 2);
89 void Style::Set( const Color
& rColorPrim
, const Color
& rColorSecn
, const Color
& rColorGap
, bool bUseGapColor
, double nP
, double nD
, double nS
)
91 maColorPrim
= rColorPrim
;
92 maColorSecn
= rColorSecn
;
93 maColorGap
= rColorGap
;
94 mbUseGapColor
= bUseGapColor
;
98 void Style::Set( const SvxBorderLine
* pBorder
, double fScale
, sal_uInt16 nMaxWidth
)
100 if(nullptr == pBorder
)
106 maColorPrim
= pBorder
->GetColorOut();
107 maColorSecn
= pBorder
->GetColorIn();
108 maColorGap
= pBorder
->GetColorGap();
109 mbUseGapColor
= pBorder
->HasGapColor();
111 const sal_uInt16
nPrim(pBorder
->GetOutWidth());
112 const sal_uInt16
nDist(pBorder
->GetDistance());
113 const sal_uInt16
nSecn(pBorder
->GetInWidth());
115 mnType
= pBorder
->GetBorderLineStyle();
116 mfPatternScale
= fScale
;
118 if( !nSecn
) // no or single frame border
120 Set( std::min
<double>(nPrim
* fScale
, nMaxWidth
), 0, 0 );
124 Set(std::min
<double>(nPrim
* fScale
, nMaxWidth
), std::min
<double>(nDist
* fScale
, nMaxWidth
), std::min
<double>(nSecn
* fScale
, nMaxWidth
));
125 // Enlarge the style if distance is too small due to rounding losses.
126 double nPixWidth
= std::min
<double>((nPrim
+ nDist
+ nSecn
) * fScale
, nMaxWidth
);
128 if( nPixWidth
> GetWidth() )
130 mfDist
= nPixWidth
- mfPrim
- mfSecn
;
133 // Shrink the style if it is too thick for the control.
134 while( GetWidth() > nMaxWidth
)
136 // First decrease space between lines.
143 // Still too thick? Decrease the line widths.
144 if (mfPrim
!= 0.0 && rtl::math::approxEqual(mfPrim
, mfSecn
))
146 // Both lines equal - decrease both to keep symmetry.
152 // Decrease each line for itself
156 if ((GetWidth() > nMaxWidth
) && mfSecn
!= 0.0)
162 Style
& Style::MirrorSelf()
166 std::swap( mfPrim
, mfSecn
);
167 // also need to swap colors
168 std::swap( maColorPrim
, maColorSecn
);
171 if( meRefMode
!= RefMode::Centered
)
173 meRefMode
= (meRefMode
== RefMode::Begin
) ? RefMode::End
: RefMode::Begin
;
179 bool Style::operator==( const Style
& rOther
) const
181 return (Prim() == rOther
.Prim()
182 && Dist() == rOther
.Dist()
183 && Secn() == rOther
.Secn()
184 && GetColorPrim() == rOther
.GetColorPrim()
185 && GetColorSecn() == rOther
.GetColorSecn()
186 && GetColorGap() == rOther
.GetColorGap()
187 && GetRefMode() == rOther
.GetRefMode()
188 && UseGapColor() == rOther
.UseGapColor()
189 && Type() == rOther
.Type());
195 * Gets the weight of rStyle, according to [MS-OI29500] v20171130, 2.1.168 Part 1 Section 17.4.66,
196 * tcBorders (Table Cell Borders).
198 double GetWordTableCellBorderWeight(const Style
& rStyle
)
200 double fWidth
= rStyle
.GetWidth();
201 int nBorderNumber
= 0;
203 // See lcl_convertBorderStyleFromToken() in writerfilter/ and ConvertBorderStyleFromWord() in
204 // editeng/, this is the opposite of the combination of those functions.
205 switch (rStyle
.Type())
207 case SvxBorderLineStyle::NONE
:
209 case SvxBorderLineStyle::DOTTED
:
210 case SvxBorderLineStyle::DASHED
:
212 case SvxBorderLineStyle::SOLID
:
218 case SvxBorderLineStyle::DOUBLE
:
219 case SvxBorderLineStyle::DOUBLE_THIN
:
223 // dashDotStroked = 23
226 case SvxBorderLineStyle::DASH_DOT
:
230 case SvxBorderLineStyle::DASH_DOT_DOT
:
234 case SvxBorderLineStyle::THINTHICK_SMALLGAP
:
235 // thinThickSmallGap = 11
238 case SvxBorderLineStyle::THICKTHIN_SMALLGAP
:
239 // thickThinSmallGap = 12
240 // thinThickThinSmallGap = 13
243 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP
:
244 // thinThickMediumGap = 14
247 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP
:
248 // thickThinMediumGap = 15
249 // thinThickThinMediumGap = 16
252 case SvxBorderLineStyle::THINTHICK_LARGEGAP
:
253 // thinThickLargeGap = 17
256 case SvxBorderLineStyle::THICKTHIN_LARGEGAP
:
257 // thickThinLargeGap = 18
258 // thinThickThinLargeGap = 19
261 case SvxBorderLineStyle::FINE_DASHED
:
265 case SvxBorderLineStyle::EMBOSSED
:
269 case SvxBorderLineStyle::ENGRAVED
:
270 // threeDEngrave = 25
273 case SvxBorderLineStyle::OUTSET
:
277 case SvxBorderLineStyle::INSET
:
283 return nBorderNumber
* fWidth
;
287 bool Style::operator<( const Style
& rOther
) const
291 // The below code would first compare based on the border width, Word compares based on its
292 // calculated weight, do that in the compat case.
293 double fLW
= GetWordTableCellBorderWeight(*this);
294 double fRW
= GetWordTableCellBorderWeight(rOther
);
295 if (!rtl::math::approxEqual(fLW
, fRW
))
301 // different total widths -> this<rOther, if this is thinner
302 double nLW
= GetWidth();
303 double nRW
= rOther
.GetWidth();
304 if( !rtl::math::approxEqual(nLW
, nRW
) ) return nLW
< nRW
;
306 // one line double, the other single -> this<rOther, if this is single
307 if( (Secn() == 0) != (rOther
.Secn() == 0) ) return Secn() == 0;
309 // both lines double with different distances -> this<rOther, if distance of this greater
310 if( (Secn() && rOther
.Secn()) && !rtl::math::approxEqual(Dist(), rOther
.Dist()) ) return Dist() > rOther
.Dist();
312 // both lines single and 1 unit thick, only one is dotted -> this<rOther, if this is dotted
313 if ((nLW
== 1) && !Secn() && !rOther
.Secn() && (Type() != rOther
.Type())) return Type() > rOther
.Type();
320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */