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
26
27
28using namespace ::com::sun::star;
29using namespace editeng;
30
31namespace svx::frame
32{
33
34Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale )
35{
36 Clear();
37 mnType = nType;
38 mfPatternScale = fScale;
39 Set( nP, nD, nS );
40}
41
42Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale )
43{
44 Clear();
45 mnType = nType;
46 mfPatternScale = fScale;
47 Set( rColorPrim, rColorSecn, rColorGap, bUseGapColor, nP, nD, nS );
48}
49
50Style::Style( const editeng::SvxBorderLine* pBorder, double fScale )
51{
52 Clear();
53 if(nullptr != pBorder)
54 {
55 mfPatternScale = fScale;
56 Set( pBorder, fScale );
57 }
58}
59
61{
64 maColorGap = Color();
65 mbUseGapColor = false;
67 mfPrim = 0.0;
68 mfDist = 0.0;
69 mfSecn = 0.0;
70 mfPatternScale = 1.0;
71 mnType = SvxBorderLineStyle::SOLID;
72 mbWordTableCell = false;
73}
74
75void Style::Set( double nP, double nD, double nS )
76{
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
83 */
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);
87}
88
89void Style::Set( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS )
90{
91 maColorPrim = rColorPrim;
92 maColorSecn = rColorSecn;
93 maColorGap = rColorGap;
94 mbUseGapColor = bUseGapColor;
95 Set( nP, nD, nS );
96}
97
98void Style::Set( const SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth )
99{
100 if(nullptr == pBorder)
101 {
102 Clear();
103 return;
104 }
105
106 maColorPrim = pBorder->GetColorOut();
107 maColorSecn = pBorder->GetColorIn();
108 maColorGap = pBorder->GetColorGap();
109 mbUseGapColor = pBorder->HasGapColor();
110
111 const sal_uInt16 nPrim(pBorder->GetOutWidth());
112 const sal_uInt16 nDist(pBorder->GetDistance());
113 const sal_uInt16 nSecn(pBorder->GetInWidth());
114
115 mnType = pBorder->GetBorderLineStyle();
116 mfPatternScale = fScale;
117
118 if( !nSecn ) // no or single frame border
119 {
120 Set( std::min<double>(nPrim * fScale, nMaxWidth), 0, 0 );
121 }
122 else
123 {
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);
127
128 if( nPixWidth > GetWidth() )
129 {
130 mfDist = nPixWidth - mfPrim - mfSecn;
131 }
132
133 // Shrink the style if it is too thick for the control.
134 while( GetWidth() > nMaxWidth )
135 {
136 // First decrease space between lines.
137 if (mfDist)
138 {
139 --mfDist;
140 continue;
141 }
142
143 // Still too thick? Decrease the line widths.
144 if (mfPrim != 0.0 && rtl::math::approxEqual(mfPrim, mfSecn))
145 {
146 // Both lines equal - decrease both to keep symmetry.
147 --mfPrim;
148 --mfSecn;
149 continue;
150 }
151
152 // Decrease each line for itself
153 if (mfPrim)
154 --mfPrim;
155
156 if ((GetWidth() > nMaxWidth) && mfSecn != 0.0)
157 --mfSecn;
158 }
159 }
160}
161
163{
164 if (mfSecn)
165 {
166 std::swap( mfPrim, mfSecn );
167 // also need to swap colors
168 std::swap( maColorPrim, maColorSecn );
169 }
170
172 {
174 }
175
176 return *this;
177}
178
179bool Style::operator==( const Style& rOther) const
180{
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());
190}
191
192namespace
193{
198double GetWordTableCellBorderWeight(const Style& rStyle)
199{
200 double fWidth = rStyle.GetWidth();
201 int nBorderNumber = 0;
202
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())
206 {
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;
281 }
282
283 return nBorderNumber * fWidth;
284}
285}
286
287bool Style::operator<( const Style& rOther) const
288{
289 if (mbWordTableCell)
290 {
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))
296 {
297 return fLW < fRW;
298 }
299 }
300
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;
305
306 // one line double, the other single -> this<rOther, if this is single
307 if( (Secn() == 0) != (rOther.Secn() == 0) ) return Secn() == 0;
308
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();
311
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();
314
315 // seem to be equal
316 return false;
317}
318}
319
320/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SvxBorderLineStyle
sal_uInt16 GetDistance() const
Color GetColorIn(bool bLeftOrTop=true) const
sal_uInt16 GetOutWidth() const
sal_uInt16 GetInWidth() const
Color GetColorOut(bool bLeftOrTop=true) const
bool HasGapColor() const
Color GetColorGap() const
SvxBorderLineStyle GetBorderLineStyle() const
Contains the widths of primary and secondary line of a frame style.
Definition: framelink.hxx:99
double Secn() const
Definition: framelink.hxx:130
void Clear()
Sets the frame style to invisible state.
Definition: framelink.cxx:60
double mfDist
Width of primary (single, left, or top) line.
Definition: framelink.hxx:105
double mfPatternScale
Width of secondary (right or bottom) line.
Definition: framelink.hxx:107
void Set(double nP, double nD, double nS)
Sets the frame style to the passed line widths.
Definition: framelink.cxx:75
Color GetColorGap() const
Definition: framelink.hxx:126
Color GetColorSecn() const
Definition: framelink.hxx:125
double GetWidth() const
Returns the total width of this frame style.
Definition: framelink.hxx:139
RefMode meRefMode
Scale used for line pattern spacing.
Definition: framelink.hxx:108
Color GetColorPrim() const
Definition: framelink.hxx:124
bool UseGapColor() const
Definition: framelink.hxx:127
double Prim() const
Definition: framelink.hxx:128
SvxBorderLineStyle mnType
Reference point handling for this frame border.
Definition: framelink.hxx:109
Style & MirrorSelf()
Mirrors this style (exchanges primary and secondary), if it is a double frame style.
Definition: framelink.cxx:162
Style()
Constructs an invisible frame style.
Definition: framelink.hxx:170
RefMode GetRefMode() const
Definition: framelink.hxx:123
double mfSecn
Distance between primary and secondary line.
Definition: framelink.hxx:106
SvxBorderLineStyle Type() const
Definition: framelink.hxx:132
bool operator==(const Style &rOther) const
Definition: framelink.cxx:179
double Dist() const
Definition: framelink.hxx:129
bool operator<(const Style &rOther) const
Definition: framelink.cxx:287
Type
@ Begin
The reference points specify the begin of the frame border width.
@ End
The reference points specify the end of the frame border width.
@ Centered
Frame borders are drawn centered to the reference points.
QPRO_FUNC_TYPE nType