LibreOffice Module svx (master)  1
framelink.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 <sal/config.h>
21 
22 #include <rtl/math.hxx>
23 #include <svx/framelink.hxx>
24 
25 #include <editeng/borderline.hxx>
26 
27 
28 using namespace ::com::sun::star;
29 using namespace editeng;
30 
31 namespace svx::frame
32 {
33 
34 Style::Style()
35 {
36  Clear();
37 }
38 
39 Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale )
40 {
41  Clear();
42  mnType = nType;
43  mfPatternScale = fScale;
44  Set( nP, nD, nS );
45 }
46 
47 Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale )
48 {
49  Clear();
50  mnType = nType;
51  mfPatternScale = fScale;
52  Set( rColorPrim, rColorSecn, rColorGap, bUseGapColor, nP, nD, nS );
53 }
54 
55 Style::Style( const editeng::SvxBorderLine* pBorder, double fScale )
56 {
57  Clear();
58  if(nullptr != pBorder)
59  {
60  mfPatternScale = fScale;
61  Set( pBorder, fScale );
62  }
63 }
64 
65 void Style::Clear()
66 {
67  maColorPrim = Color();
68  maColorSecn = Color();
69  maColorGap = Color();
70  mbUseGapColor = false;
71  meRefMode = RefMode::Centered;
72  mfPrim = 0.0;
73  mfDist = 0.0;
74  mfSecn = 0.0;
75  mfPatternScale = 1.0;
76  mnType = SvxBorderLineStyle::SOLID;
77  mbWordTableCell = false;
78 }
79 
80 void Style::Set( double nP, double nD, double nS )
81 {
82  /* nP nD nS -> mfPrim mfDist mfSecn
83  --------------------------------------
84  any any 0 nP 0 0
85  0 any >0 nS 0 0
86  >0 0 >0 nP 0 0
87  >0 >0 >0 nP nD nS
88  */
89  mfPrim = rtl::math::round(nP ? nP : nS, 2);
90  mfDist = rtl::math::round((nP && nS) ? nD : 0, 2);
91  mfSecn = rtl::math::round((nP && nD) ? nS : 0, 2);
92 }
93 
94 void Style::Set( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS )
95 {
96  maColorPrim = rColorPrim;
97  maColorSecn = rColorSecn;
98  maColorGap = rColorGap;
99  mbUseGapColor = bUseGapColor;
100  Set( nP, nD, nS );
101 }
102 
103 void Style::Set( const SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth )
104 {
105  if(nullptr == pBorder)
106  {
107  Clear();
108  return;
109  }
110 
111  maColorPrim = pBorder->GetColorOut();
112  maColorSecn = pBorder->GetColorIn();
113  maColorGap = pBorder->GetColorGap();
114  mbUseGapColor = pBorder->HasGapColor();
115 
116  const sal_uInt16 nPrim(pBorder->GetOutWidth());
117  const sal_uInt16 nDist(pBorder->GetDistance());
118  const sal_uInt16 nSecn(pBorder->GetInWidth());
119 
120  mnType = pBorder->GetBorderLineStyle();
121  mfPatternScale = fScale;
122 
123  if( !nSecn ) // no or single frame border
124  {
125  Set( std::min<double>(nPrim * fScale, nMaxWidth), 0, 0 );
126  }
127  else
128  {
129  Set(std::min<double>(nPrim * fScale, nMaxWidth), std::min<double>(nDist * fScale, nMaxWidth), std::min<double>(nSecn * fScale, nMaxWidth));
130  // Enlarge the style if distance is too small due to rounding losses.
131  double nPixWidth = std::min<double>((nPrim + nDist + nSecn) * fScale, nMaxWidth);
132 
133  if( nPixWidth > GetWidth() )
134  {
135  mfDist = nPixWidth - mfPrim - mfSecn;
136  }
137 
138  // Shrink the style if it is too thick for the control.
139  while( GetWidth() > nMaxWidth )
140  {
141  // First decrease space between lines.
142  if (mfDist)
143  {
144  --mfDist;
145  continue;
146  }
147 
148  // Still too thick? Decrease the line widths.
149  if (mfPrim != 0.0 && rtl::math::approxEqual(mfPrim, mfSecn))
150  {
151  // Both lines equal - decrease both to keep symmetry.
152  --mfPrim;
153  --mfSecn;
154  continue;
155  }
156 
157  // Decrease each line for itself
158  if (mfPrim)
159  --mfPrim;
160 
161  if ((GetWidth() > nMaxWidth) && mfSecn != 0.0)
162  --mfSecn;
163  }
164  }
165 }
166 
167 Style& Style::MirrorSelf()
168 {
169  if (mfSecn)
170  {
171  std::swap( mfPrim, mfSecn );
172  // also need to swap colors
173  std::swap( maColorPrim, maColorSecn );
174  }
175 
176  if( meRefMode != RefMode::Centered )
177  {
178  meRefMode = (meRefMode == RefMode::Begin) ? RefMode::End : RefMode::Begin;
179  }
180 
181  return *this;
182 }
183 
184 bool Style::operator==( const Style& rOther) const
185 {
186  return (Prim() == rOther.Prim()
187  && Dist() == rOther.Dist()
188  && Secn() == rOther.Secn()
189  && GetColorPrim() == rOther.GetColorPrim()
190  && GetColorSecn() == rOther.GetColorSecn()
191  && GetColorGap() == rOther.GetColorGap()
192  && GetRefMode() == rOther.GetRefMode()
193  && UseGapColor() == rOther.UseGapColor()
194  && Type() == rOther.Type());
195 }
196 
197 namespace
198 {
203 double GetWordTableCellBorderWeight(const Style& rStyle)
204 {
205  double fWidth = rStyle.GetWidth();
206  int nBorderNumber = 0;
207 
208  // See lcl_convertBorderStyleFromToken() in writerfilter/ and ConvertBorderStyleFromWord() in
209  // editeng/, this is the opposite of the combination of those functions.
210  switch (rStyle.Type())
211  {
212  case SvxBorderLineStyle::NONE:
213  return 0.0;
214  case SvxBorderLineStyle::DOTTED:
215  case SvxBorderLineStyle::DASHED:
216  return 1.0;
217  case SvxBorderLineStyle::SOLID:
218  // single = 1
219  // thick = 2
220  // wave = 20
221  nBorderNumber = 1;
222  break;
223  case SvxBorderLineStyle::DOUBLE:
224  case SvxBorderLineStyle::DOUBLE_THIN:
225  // double = 3
226  // triple = 10
227  // doubleWave = 21
228  // dashDotStroked = 23
229  nBorderNumber = 3;
230  break;
231  case SvxBorderLineStyle::DASH_DOT:
232  // dotDash = 8
233  nBorderNumber = 8;
234  break;
235  case SvxBorderLineStyle::DASH_DOT_DOT:
236  // dotDotDash = 9
237  nBorderNumber = 9;
238  break;
239  case SvxBorderLineStyle::THINTHICK_SMALLGAP:
240  // thinThickSmallGap = 11
241  nBorderNumber = 11;
242  break;
243  case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
244  // thickThinSmallGap = 12
245  // thinThickThinSmallGap = 13
246  nBorderNumber = 12;
247  break;
248  case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
249  // thinThickMediumGap = 14
250  nBorderNumber = 14;
251  break;
252  case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
253  // thickThinMediumGap = 15
254  // thinThickThinMediumGap = 16
255  nBorderNumber = 15;
256  break;
257  case SvxBorderLineStyle::THINTHICK_LARGEGAP:
258  // thinThickLargeGap = 17
259  nBorderNumber = 17;
260  break;
261  case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
262  // thickThinLargeGap = 18
263  // thinThickThinLargeGap = 19
264  nBorderNumber = 18;
265  break;
266  case SvxBorderLineStyle::FINE_DASHED:
267  // dashSmallGap = 22
268  nBorderNumber = 22;
269  break;
270  case SvxBorderLineStyle::EMBOSSED:
271  // threeDEmboss = 24
272  nBorderNumber = 24;
273  break;
274  case SvxBorderLineStyle::ENGRAVED:
275  // threeDEngrave = 25
276  nBorderNumber = 25;
277  break;
278  case SvxBorderLineStyle::OUTSET:
279  // outset = 26
280  nBorderNumber = 25;
281  break;
282  case SvxBorderLineStyle::INSET:
283  // inset = 27
284  nBorderNumber = 27;
285  break;
286  }
287 
288  return nBorderNumber * fWidth;
289 }
290 }
291 
292 bool Style::operator<( const Style& rOther) const
293 {
294  if (mbWordTableCell)
295  {
296  // The below code would first compare based on the border width, Word compares based on its
297  // calculated weight, do that in the compat case.
298  double fLW = GetWordTableCellBorderWeight(*this);
299  double fRW = GetWordTableCellBorderWeight(rOther);
300  if (!rtl::math::approxEqual(fLW, fRW))
301  {
302  return fLW < fRW;
303  }
304  }
305 
306  // different total widths -> this<rOther, if this is thinner
307  double nLW = GetWidth();
308  double nRW = rOther.GetWidth();
309  if( !rtl::math::approxEqual(nLW, nRW) ) return nLW < nRW;
310 
311  // one line double, the other single -> this<rOther, if this is single
312  if( (Secn() == 0) != (rOther.Secn() == 0) ) return Secn() == 0;
313 
314  // both lines double with different distances -> this<rOther, if distance of this greater
315  if( (Secn() && rOther.Secn()) && !rtl::math::approxEqual(Dist(), rOther.Dist()) ) return Dist() > rOther.Dist();
316 
317  // both lines single and 1 unit thick, only one is dotted -> this<rOther, if this is dotted
318  if ((nLW == 1) && !Secn() && !rOther.Secn() && (Type() != rOther.Type())) return Type() > rOther.Type();
319 
320  // seem to be equal
321  return false;
322 }
323 }
324 
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Type
double Dist() const
Definition: framelink.hxx:129
RefMode GetRefMode() const
Definition: framelink.hxx:123
SvxBorderLineStyle Type() const
Definition: framelink.hxx:132
Color GetColorSecn() const
Definition: framelink.hxx:125
double GetWidth() const
Returns the total width of this frame style.
Definition: framelink.hxx:139
Color GetColorGap() const
Definition: framelink.hxx:126
bool UseGapColor() const
Definition: framelink.hxx:127
SvxBorderLineStyle
sal_uInt16 GetOutWidth() const
double Secn() const
Definition: framelink.hxx:130
sal_Int32 mnType
sal_uInt16 GetDistance() const
bool HasGapColor() const
Color GetColorOut(bool bLeftOrTop=true) const
Color GetColorIn(bool bLeftOrTop=true) const
Color GetColorPrim() const
Definition: framelink.hxx:124
bool operator<(const Subset &rLHS, const Subset &rRHS)
Definition: ucsubset.hxx:50
Contains the widths of primary and secondary line of a frame style.
Definition: framelink.hxx:98
SvxBorderLineStyle GetBorderLineStyle() const
Color GetColorGap() const
double Prim() const
Definition: framelink.hxx:128
sal_uInt16 GetInWidth() const