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 // Classes
35 void Style::implEnsureImplStyle()
36 {
37  if(!maImplStyle)
38  {
39  maImplStyle = std::make_shared<implStyle>();
40  }
41 }
42 
43 Style::Style() :
44  maImplStyle()
45 {
46 }
47 
48 Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale ) :
49  maImplStyle(std::make_shared<implStyle>())
50 {
51  maImplStyle->mnType = nType;
52  maImplStyle->mfPatternScale = fScale;
53  Set( nP, nD, nS );
54 }
55 
56 Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale ) :
57  maImplStyle(std::make_shared<implStyle>())
58 {
59  maImplStyle->mnType = nType;
60  maImplStyle->mfPatternScale = fScale;
61  Set( rColorPrim, rColorSecn, rColorGap, bUseGapColor, nP, nD, nS );
62 }
63 
64 Style::Style( const editeng::SvxBorderLine* pBorder, double fScale ) :
65  maImplStyle()
66 {
67  if(nullptr != pBorder)
68  {
69  maImplStyle = std::make_shared<implStyle>();
70  maImplStyle->mfPatternScale = fScale;
71  Set( pBorder, fScale );
72  }
73 }
74 
76 {
77  if(maImplStyle)
78  {
79  maImplStyle.reset();
80  }
81 }
82 
83 void Style::Set( double nP, double nD, double nS )
84 {
85  /* nP nD nS -> mfPrim mfDist mfSecn
86  --------------------------------------
87  any any 0 nP 0 0
88  0 any >0 nS 0 0
89  >0 0 >0 nP 0 0
90  >0 >0 >0 nP nD nS
91  */
93  implStyle* pTarget = maImplStyle.get();
94  pTarget->mfPrim = rtl::math::round(nP ? nP : nS, 2);
95  pTarget->mfDist = rtl::math::round((nP && nS) ? nD : 0, 2);
96  pTarget->mfSecn = rtl::math::round((nP && nD) ? nS : 0, 2);
97 }
98 
99 void Style::Set( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS )
100 {
102  implStyle* pTarget = maImplStyle.get();
103  pTarget->maColorPrim = rColorPrim;
104  pTarget->maColorSecn = rColorSecn;
105  pTarget->maColorGap = rColorGap;
106  pTarget->mbUseGapColor = bUseGapColor;
107  Set( nP, nD, nS );
108 }
109 
110 void Style::Set( const SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth )
111 {
112  if(nullptr == pBorder)
113  {
114  Clear();
115  return;
116  }
117 
119  implStyle* pTarget = maImplStyle.get();
120  pTarget->maColorPrim = pBorder->GetColorOut();
121  pTarget->maColorSecn = pBorder->GetColorIn();
122  pTarget->maColorGap = pBorder->GetColorGap();
123  pTarget->mbUseGapColor = pBorder->HasGapColor();
124 
125  const sal_uInt16 nPrim(pBorder->GetOutWidth());
126  const sal_uInt16 nDist(pBorder->GetDistance());
127  const sal_uInt16 nSecn(pBorder->GetInWidth());
128 
129  pTarget->mnType = pBorder->GetBorderLineStyle();
130  pTarget->mfPatternScale = fScale;
131 
132  if( !nSecn ) // no or single frame border
133  {
134  Set( std::min<double>(nPrim * fScale, nMaxWidth), 0, 0 );
135  }
136  else
137  {
138  Set(std::min<double>(nPrim * fScale, nMaxWidth), std::min<double>(nDist * fScale, nMaxWidth), std::min<double>(nSecn * fScale, nMaxWidth));
139  // Enlarge the style if distance is too small due to rounding losses.
140  double nPixWidth = std::min<double>((nPrim + nDist + nSecn) * fScale, nMaxWidth);
141 
142  if( nPixWidth > GetWidth() )
143  {
144  pTarget->mfDist = nPixWidth - pTarget->mfPrim - pTarget->mfSecn;
145  }
146 
147  // Shrink the style if it is too thick for the control.
148  while( GetWidth() > nMaxWidth )
149  {
150  // First decrease space between lines.
151  if (pTarget->mfDist)
152  {
153  --(pTarget->mfDist);
154  continue;
155  }
156 
157  // Still too thick? Decrease the line widths.
158  if (pTarget->mfPrim != 0.0 && rtl::math::approxEqual(pTarget->mfPrim, pTarget->mfSecn))
159  {
160  // Both lines equal - decrease both to keep symmetry.
161  --(pTarget->mfPrim);
162  --(pTarget->mfSecn);
163  continue;
164  }
165 
166  // Decrease each line for itself
167  if (pTarget->mfPrim)
168  {
169  --(pTarget->mfPrim);
170  }
171 
172  if ((GetWidth() > nMaxWidth) && pTarget->mfSecn != 0.0)
173  {
174  --(pTarget->mfSecn);
175  }
176  }
177  }
178 }
179 
180 void Style::SetRefMode( RefMode eRefMode )
181 {
182  if(!maImplStyle)
183  {
184  if(RefMode::Centered == eRefMode)
185  {
186  return;
187  }
188 
190  }
191 
192  maImplStyle->meRefMode = eRefMode;
193 }
194 
195 void Style::SetColorPrim( const Color& rColor )
196 {
197  if(!maImplStyle)
198  {
199  if(Color() == rColor)
200  {
201  return;
202  }
203 
205  }
206 
207  maImplStyle->maColorPrim = rColor;
208 }
209 
210 void Style::SetColorSecn( const Color& rColor )
211 {
212  if(!maImplStyle)
213  {
214  if(Color() == rColor)
215  {
216  return;
217  }
218 
220  }
221 
222  maImplStyle->maColorSecn = rColor;
223 }
224 
226 {
227  if(!maImplStyle)
228  {
229  if(SvxBorderLineStyle::SOLID == nType)
230  {
231  return;
232  }
233 
235  }
236 
237  maImplStyle->mnType = nType;
238 }
239 
241 {
242  if(!maImplStyle)
243  {
244  return *this;
245  }
246 
247  implStyle* pTarget = maImplStyle.get();
248 
249  if (pTarget->mfSecn)
250  {
251  std::swap( pTarget->mfPrim, pTarget->mfSecn );
252  // also need to swap colors
253  std::swap( pTarget->maColorPrim, pTarget->maColorSecn );
254  }
255 
256  if( pTarget->meRefMode != RefMode::Centered )
257  {
258  pTarget->meRefMode = (pTarget->meRefMode == RefMode::Begin) ? RefMode::End : RefMode::Begin;
259  }
260 
261  return *this;
262 }
263 
264 void Style::SetWordTableCell(bool bWordTableCell)
265 {
266  if (!maImplStyle)
267  {
269  }
270 
271  maImplStyle->mbWordTableCell = bWordTableCell;
272 }
273 
274 bool Style::operator==( const Style& rOther) const
275 {
276  if(!maImplStyle && !rOther.maImplStyle)
277  {
278  return true;
279  }
280 
281  if(maImplStyle && rOther.maImplStyle && maImplStyle.get() == rOther.maImplStyle.get())
282  {
283  return true;
284  }
285 
286  return (Prim() == rOther.Prim()
287  && Dist() == rOther.Dist()
288  && Secn() == rOther.Secn()
289  && GetColorPrim() == rOther.GetColorPrim()
290  && GetColorSecn() == rOther.GetColorSecn()
291  && GetColorGap() == rOther.GetColorGap()
292  && GetRefMode() == rOther.GetRefMode()
293  && UseGapColor() == rOther.UseGapColor()
294  && Type() == rOther.Type());
295 }
296 
297 namespace
298 {
303 double GetWordTableCellBorderWeight(const Style& rStyle)
304 {
305  double fWidth = rStyle.GetWidth();
306  int nBorderNumber = 0;
307 
308  // See lcl_convertBorderStyleFromToken() in writerfilter/ and ConvertBorderStyleFromWord() in
309  // editeng/, this is the opposite of the combination of those functions.
310  switch (rStyle.Type())
311  {
312  case SvxBorderLineStyle::NONE:
313  return 0.0;
314  case SvxBorderLineStyle::DOTTED:
315  case SvxBorderLineStyle::DASHED:
316  return 1.0;
317  case SvxBorderLineStyle::SOLID:
318  // single = 1
319  // thick = 2
320  // wave = 20
321  nBorderNumber = 1;
322  break;
323  case SvxBorderLineStyle::DOUBLE:
324  case SvxBorderLineStyle::DOUBLE_THIN:
325  // double = 3
326  // triple = 10
327  // doubleWave = 21
328  // dashDotStroked = 23
329  nBorderNumber = 3;
330  break;
331  case SvxBorderLineStyle::DASH_DOT:
332  // dotDash = 8
333  nBorderNumber = 8;
334  break;
335  case SvxBorderLineStyle::DASH_DOT_DOT:
336  // dotDotDash = 9
337  nBorderNumber = 9;
338  break;
339  case SvxBorderLineStyle::THINTHICK_SMALLGAP:
340  // thinThickSmallGap = 11
341  nBorderNumber = 11;
342  break;
343  case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
344  // thickThinSmallGap = 12
345  // thinThickThinSmallGap = 13
346  nBorderNumber = 12;
347  break;
348  case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
349  // thinThickMediumGap = 14
350  nBorderNumber = 14;
351  break;
352  case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
353  // thickThinMediumGap = 15
354  // thinThickThinMediumGap = 16
355  nBorderNumber = 15;
356  break;
357  case SvxBorderLineStyle::THINTHICK_LARGEGAP:
358  // thinThickLargeGap = 17
359  nBorderNumber = 17;
360  break;
361  case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
362  // thickThinLargeGap = 18
363  // thinThickThinLargeGap = 19
364  nBorderNumber = 18;
365  break;
366  case SvxBorderLineStyle::FINE_DASHED:
367  // dashSmallGap = 22
368  nBorderNumber = 22;
369  break;
370  case SvxBorderLineStyle::EMBOSSED:
371  // threeDEmboss = 24
372  nBorderNumber = 24;
373  break;
374  case SvxBorderLineStyle::ENGRAVED:
375  // threeDEngrave = 25
376  nBorderNumber = 25;
377  break;
378  case SvxBorderLineStyle::OUTSET:
379  // outset = 26
380  nBorderNumber = 25;
381  break;
382  case SvxBorderLineStyle::INSET:
383  // inset = 27
384  nBorderNumber = 27;
385  break;
386  }
387 
388  return nBorderNumber * fWidth;
389 }
390 }
391 
392 bool Style::operator<( const Style& rOther) const
393 {
394  if(!maImplStyle && !rOther.maImplStyle)
395  {
396  // are equal
397  return false;
398  }
399 
400  if (maImplStyle && maImplStyle->mbWordTableCell)
401  {
402  // The below code would first compare based on the border width, Word compares based on its
403  // calculated weight, do that in the compat case.
404  double fLW = GetWordTableCellBorderWeight(*this);
405  double fRW = GetWordTableCellBorderWeight(rOther);
406  if (!rtl::math::approxEqual(fLW, fRW))
407  {
408  return fLW < fRW;
409  }
410  }
411 
412  // different total widths -> this<rOther, if this is thinner
413  double nLW = GetWidth();
414  double nRW = rOther.GetWidth();
415  if( !rtl::math::approxEqual(nLW, nRW) ) return nLW < nRW;
416 
417  // one line double, the other single -> this<rOther, if this is single
418  if( (Secn() == 0) != (rOther.Secn() == 0) ) return Secn() == 0;
419 
420  // both lines double with different distances -> this<rOther, if distance of this greater
421  if( (Secn() && rOther.Secn()) && !rtl::math::approxEqual(Dist(), rOther.Dist()) ) return Dist() > rOther.Dist();
422 
423  // both lines single and 1 unit thick, only one is dotted -> this<rOther, if this is dotted
424  if ((nLW == 1) && !Secn() && !rOther.Secn() && (Type() != rOther.Type())) return Type() > rOther.Type();
425 
426  // seem to be equal
427  return false;
428 }
429 }
430 
431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double mfSecn
Distance between primary and secondary line.
Definition: framelink.hxx:116
double Dist() const
Definition: framelink.hxx:160
Style()
Constructs an invisible frame style.
Definition: framelink.cxx:43
std::shared_ptr< implStyle > maImplStyle
the impl class holding the data
Definition: framelink.hxx:139
bool operator==(const Style &rOther) const
Definition: framelink.cxx:274
void implEnsureImplStyle()
call to set maImplStyle on demand
Definition: framelink.cxx:35
RefMode GetRefMode() const
Definition: framelink.hxx:154
SvxBorderLineStyle Type() const
Definition: framelink.hxx:163
Color GetColorSecn() const
Definition: framelink.hxx:156
The reference points specify the end of the frame border width.
double GetWidth() const
Returns the total width of this frame style.
Definition: framelink.hxx:170
std::shared_ptr< T > make_shared(Args &&...args)
Color GetColorGap() const
Definition: framelink.hxx:157
bool UseGapColor() const
Definition: framelink.hxx:158
SvxBorderLineStyle
sal_uInt16 GetOutWidth() const
SvxBorderLineStyle mnType
Scale used for line pattern spacing.
Definition: framelink.hxx:118
void Clear()
Sets the frame style to invisible state.
Definition: framelink.cxx:75
double Secn() const
Definition: framelink.hxx:161
void SetColorSecn(const Color &rColor)
Definition: framelink.cxx:210
sal_uInt16 GetDistance() const
bool HasGapColor() const
Color GetColorOut(bool bLeftOrTop=true) const
Color GetColorIn(bool bLeftOrTop=true) const
void SetType(SvxBorderLineStyle nType)
Sets whether to use dotted style for single hair lines.
Definition: framelink.cxx:225
Color GetColorPrim() const
Definition: framelink.hxx:155
Style & MirrorSelf()
Mirrors this style (exchanges primary and secondary), if it is a double frame style.
Definition: framelink.cxx:240
void SetWordTableCell(bool bWordTableCell)
Enables the Word-compatible Style comparison code.
Definition: framelink.cxx:264
Frame borders are drawn centered to the reference points.
double mfDist
Width of primary (single, left, or top) line.
Definition: framelink.hxx:115
Contains the widths of primary and secondary line of a frame style.
Definition: framelink.hxx:101
void Set(double nP, double nD, double nS)
Sets the frame style to the passed line widths.
Definition: framelink.cxx:83
SvxBorderLineStyle GetBorderLineStyle() const
void SetColorPrim(const Color &rColor)
Sets a new color, does not modify other settings.
Definition: framelink.cxx:195
Color GetColorGap() const
void SetRefMode(RefMode eRefMode)
Sets a new reference point handling mode, does not modify other settings.
Definition: framelink.cxx:180
The reference points specify the begin of the frame border width.
double Prim() const
Definition: framelink.hxx:159
sal_uInt16 GetInWidth() const
double mfPatternScale
Width of secondary (right or bottom) line.
Definition: framelink.hxx:117
bool operator<(const Style &rOther) const
Definition: framelink.cxx:392
RefMode
Specifies how the reference points for frame borders are used.
Definition: framelink.hxx:39
double mfPrim
Reference point handling for this frame border.
Definition: framelink.hxx:114