Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / dialog / framelink.cxx
blob77098bd3e80d60392d5aba0f57b94c9f36452cff
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 <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;
31 namespace svx::frame
34 Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale )
36 Clear();
37 mnType = nType;
38 mfPatternScale = fScale;
39 Set( nP, nD, nS );
42 Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale )
44 Clear();
45 mnType = nType;
46 mfPatternScale = fScale;
47 Set( rColorPrim, rColorSecn, rColorGap, bUseGapColor, nP, nD, nS );
50 Style::Style( const editeng::SvxBorderLine* pBorder, double fScale )
52 Clear();
53 if(nullptr != pBorder)
55 mfPatternScale = fScale;
56 Set( pBorder, fScale );
60 void Style::Clear()
62 maColorPrim = Color();
63 maColorSecn = Color();
64 maColorGap = Color();
65 mbUseGapColor = false;
66 meRefMode = RefMode::Centered;
67 mfPrim = 0.0;
68 mfDist = 0.0;
69 mfSecn = 0.0;
70 mfPatternScale = 1.0;
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 --------------------------------------
79 any any 0 nP 0 0
80 0 any >0 nS 0 0
81 >0 0 >0 nP 0 0
82 >0 >0 >0 nP nD nS
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;
95 Set( nP, nD, nS );
98 void Style::Set( const SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth )
100 if(nullptr == pBorder)
102 Clear();
103 return;
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 );
122 else
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.
137 if (mfDist)
139 --mfDist;
140 continue;
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.
147 --mfPrim;
148 --mfSecn;
149 continue;
152 // Decrease each line for itself
153 if (mfPrim)
154 --mfPrim;
156 if ((GetWidth() > nMaxWidth) && mfSecn != 0.0)
157 --mfSecn;
162 Style& Style::MirrorSelf()
164 if (mfSecn)
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;
176 return *this;
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());
192 namespace
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:
208 return 0.0;
209 case SvxBorderLineStyle::DOTTED:
210 case SvxBorderLineStyle::DASHED:
211 return 1.0;
212 case SvxBorderLineStyle::SOLID:
213 // single = 1
214 // thick = 2
215 // wave = 20
216 nBorderNumber = 1;
217 break;
218 case SvxBorderLineStyle::DOUBLE:
219 case SvxBorderLineStyle::DOUBLE_THIN:
220 // double = 3
221 // triple = 10
222 // doubleWave = 21
223 // dashDotStroked = 23
224 nBorderNumber = 3;
225 break;
226 case SvxBorderLineStyle::DASH_DOT:
227 // dotDash = 8
228 nBorderNumber = 8;
229 break;
230 case SvxBorderLineStyle::DASH_DOT_DOT:
231 // dotDotDash = 9
232 nBorderNumber = 9;
233 break;
234 case SvxBorderLineStyle::THINTHICK_SMALLGAP:
235 // thinThickSmallGap = 11
236 nBorderNumber = 11;
237 break;
238 case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
239 // thickThinSmallGap = 12
240 // thinThickThinSmallGap = 13
241 nBorderNumber = 12;
242 break;
243 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
244 // thinThickMediumGap = 14
245 nBorderNumber = 14;
246 break;
247 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
248 // thickThinMediumGap = 15
249 // thinThickThinMediumGap = 16
250 nBorderNumber = 15;
251 break;
252 case SvxBorderLineStyle::THINTHICK_LARGEGAP:
253 // thinThickLargeGap = 17
254 nBorderNumber = 17;
255 break;
256 case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
257 // thickThinLargeGap = 18
258 // thinThickThinLargeGap = 19
259 nBorderNumber = 18;
260 break;
261 case SvxBorderLineStyle::FINE_DASHED:
262 // dashSmallGap = 22
263 nBorderNumber = 22;
264 break;
265 case SvxBorderLineStyle::EMBOSSED:
266 // threeDEmboss = 24
267 nBorderNumber = 24;
268 break;
269 case SvxBorderLineStyle::ENGRAVED:
270 // threeDEngrave = 25
271 nBorderNumber = 25;
272 break;
273 case SvxBorderLineStyle::OUTSET:
274 // outset = 26
275 nBorderNumber = 25;
276 break;
277 case SvxBorderLineStyle::INSET:
278 // inset = 27
279 nBorderNumber = 27;
280 break;
283 return nBorderNumber * fWidth;
287 bool Style::operator<( const Style& rOther) const
289 if (mbWordTableCell)
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))
297 return 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();
315 // seem to be equal
316 return false;
320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */