Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/svx/svdtrans.hxx
Line
Count
Source
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
#pragma once
21
22
#include <rtl/ustring.hxx>
23
#include <svx/svxdllapi.h>
24
#include <tools/degree.hxx>
25
#include <tools/fldunit.hxx>
26
#include <tools/fract.hxx>
27
#include <tools/gen.hxx>
28
#include <tools/helpers.hxx>
29
#include <tools/mapunit.hxx>
30
#include <tools/poly.hxx>
31
32
// That maximum shear angle
33
inline constexpr Degree100 SDRMAXSHEAR(8900);
34
35
class XPolygon;
36
class XPolyPolygon;
37
38
0
inline void MovePoly(tools::Polygon& rPoly, const Size& S)      { rPoly.Move(S.Width(),S.Height()); }
39
void MoveXPoly(XPolygon& rPoly, const Size& S);
40
41
SVXCORE_DLLPUBLIC void ResizeRect(tools::Rectangle& rRect, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
42
inline void ResizePoint(Point& rPnt, const Point& rRef, const Fraction& xFract, const Fraction& yFract);
43
void ResizePoly(tools::Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
44
void ResizeXPoly(XPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
45
46
inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs);
47
SVXCORE_DLLPUBLIC void RotatePoly(tools::Polygon& rPoly, const Point& rRef, double sn, double cs);
48
void RotateXPoly(XPolygon& rPoly, const Point& rRef, double sn, double cs);
49
void RotateXPoly(XPolyPolygon& rPoly, const Point& rRef, double sn, double cs);
50
51
void MirrorPoint(Point& rPnt, const Point& rRef1, const Point& rRef2);
52
void MirrorXPoly(XPolygon& rPoly, const Point& rRef1, const Point& rRef2);
53
54
inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, bool bVShear = false);
55
SVXCORE_DLLPUBLIC void ShearPoly(tools::Polygon& rPoly, const Point& rRef, double tn);
56
void ShearXPoly(XPolygon& rPoly, const Point& rRef, double tn, bool bVShear = false);
57
58
/**
59
 * rPnt.X/rPnt.Y is set to rCenter.X or rCenter.Y!
60
 * We then only need to rotate rPnt by rCenter.
61
 *
62
 * @return the returned angle is in rad
63
 */
64
inline double GetCrookAngle(Point& rPnt, const Point& rCenter, const Point& rRad, bool bVertical);
65
66
/**
67
 * The following methods accept a point of an XPolygon, whereas the neighbouring
68
 * control points of the actual point are passed in pC1/pC2.
69
 * Via rSin/rCos, sin(nAngle) and cos(nAngle) are returned.
70
 *
71
 * @return the returned angle is in rad
72
 */
73
double CrookRotateXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
74
                         const Point& rRad, double& rSin, double& rCos, bool bVert);
75
double CrookSlantXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
76
                        const Point& rRad, double& rSin, double& rCos, bool bVert);
77
double CrookStretchXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
78
                          const Point& rRad, double& rSin, double& rCos, bool bVert,
79
                          const tools::Rectangle& rRefRect);
80
81
void CrookRotatePoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert);
82
void CrookSlantPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert);
83
void CrookStretchPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert, const tools::Rectangle& rRefRect);
84
85
void CrookRotatePoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert);
86
void CrookSlantPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert);
87
void CrookStretchPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert, const tools::Rectangle& rRefRect);
88
89
/**************************************************************************************************/
90
/*  Inline                                                                                        */
91
/**************************************************************************************************/
92
93
inline void ResizePoint(Point& rPnt, const Point& rRef, const Fraction& xFract, const Fraction& yFract)
94
1.44M
{
95
1.44M
    double nxFract = xFract.IsValid() ? static_cast<double>(xFract) : 1.0;
96
1.44M
    double nyFract = yFract.IsValid() ? static_cast<double>(yFract) : 1.0;
97
1.44M
    rPnt.setX(rRef.X() + basegfx::fround<tools::Long>((rPnt.X() - rRef.X()) * nxFract));
98
1.44M
    rPnt.setY(rRef.Y() + basegfx::fround<tools::Long>((rPnt.Y() - rRef.Y()) * nyFract));
99
1.44M
}
100
101
inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs)
102
2.06M
{
103
2.06M
    tools::Long dx=rPnt.X()-rRef.X();
104
2.06M
    tools::Long dy=rPnt.Y()-rRef.Y();
105
2.06M
    rPnt.setX(basegfx::fround<tools::Long>(rRef.X() + dx * cs + dy * sn));
106
2.06M
    rPnt.setY(basegfx::fround<tools::Long>(rRef.Y() + dy * cs - dx * sn));
107
2.06M
}
108
109
inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, bool bVShear)
110
255
{
111
255
    if (!bVShear) { // Horizontal
112
255
        if (rPnt.Y()!=rRef.Y()) { // else not needed
113
102
            rPnt.AdjustX(basegfx::fround<tools::Long>((rRef.Y() - rPnt.Y()) * tn));
114
102
        }
115
255
    } else { // or else vertical
116
0
        if (rPnt.X()!=rRef.X()) { // else not needed
117
0
            rPnt.AdjustY(basegfx::fround<tools::Long>((rRef.X() - rPnt.X()) * tn));
118
0
        }
119
0
    }
120
255
}
121
122
inline double GetCrookAngle(Point& rPnt, const Point& rCenter, const Point& rRad, bool bVertical)
123
0
{
124
0
    double nAngle;
125
0
    if (bVertical) {
126
0
        tools::Long dy=rPnt.Y()-rCenter.Y();
127
0
        nAngle=static_cast<double>(dy)/static_cast<double>(rRad.Y());
128
0
        rPnt.setY(rCenter.Y());
129
0
    } else {
130
0
        tools::Long dx=rCenter.X()-rPnt.X();
131
0
        nAngle=static_cast<double>(dx)/static_cast<double>(rRad.X());
132
0
        rPnt.setX(rCenter.X());
133
0
    }
134
0
    return nAngle;
135
0
}
136
137
/**************************************************************************************************/
138
/**************************************************************************************************/
139
140
/**
141
 * The Y axis points down!
142
 * The function negates the Y axis, when calculating the angle, such
143
 * that GetAngle(Point(0,-1))=90 deg.
144
 * GetAngle(Point(0,0)) returns 0.
145
 *
146
 * @return the returned value is in the range of -180.00..179.99 deg
147
 * and is in 1/100 deg units
148
 */
149
SVXCORE_DLLPUBLIC Degree100 GetAngle(const Point& rPnt);
150
151
SVXCORE_DLLPUBLIC Degree100 NormAngle18000(Degree100 a); /// Normalize angle to -180.00..179.99
152
153
SVXCORE_DLLPUBLIC Degree100 NormAngle36000(Degree100 a); /// Normalize angle to 0.00..359.99
154
155
sal_uInt16 GetAngleSector(Degree100 nAngle); /// Determine sector within the cartesian coordinate system
156
157
/**
158
 * Calculates the length of (0,0) via a^2 + b^2 = c^2
159
 * In order to avoid overflows, we ignore some decimal places.
160
 */
161
tools::Long GetLen(const Point& rPnt);
162
163
/**
164
 * The transformation of a rectangle into a polygon, by
165
 * using angle parameters from GeoStat.                          ------------
166
 * The point of reference is always the Point 0, meaning        /1        2/
167
 * the upper left corner of the initial rectangle.             /          /
168
 * When calculating the polygon, the order is first           /          /
169
 * shear and then the rotation.                              /          /
170
 *                                                          /          / \
171
 *                                                         /          /   |
172
 * A) Initial rectangle aRect  B) After applying Shear     /0        3/ Rot|
173
 * +------------------+       --------------------        ------------------
174
 * |0                1|        \0                1\       C) After applying Rotate
175
 * |                  |         \                  \
176
 * |                  |       |  \                  \
177
 * |3                2|       |   \3                2\
178
 * +------------------+       |    --------------------
179
 *                            |Shr
180
 *
181
 * When converting the polygon back into a rect, the order is necessarily the
182
 * other way around:
183
 *  - Calculating the rotation angle: angle of the line 0-1 in figure C) to the horizontal
184
 *  - Turning the sheared rect back (we get figure B)
185
 *  - Determining the width of the rect = length of the line 0-1 in figure B)
186
 *  - Determining the height of the rect = vertical distance between the points 0 and 3
187
 *    of figure B)
188
 *  - Determining the shear angle from the line 0-3 to the perpendicular line.
189
 *
190
 * We need to keep in mind that the polygon can be mirrored when it was
191
 * transformed in the meantime (e.g. mirror or resize with negative factor).
192
 * In that case, we first need to normalize, by swapping points (0 with 3 and 1
193
 * with 2), so that it has the right orientation.
194
 *
195
 * Note: a positive shear angle means a shear with a positive visible curvature
196
 * on the screen. Mathematically, that would be a negative curvature, as the
197
 * Y axis runs from top to bottom on the screen.
198
 * Rotation angle: positive means a visible left rotation.
199
 */
200
201
class GeoStat { // Geometric state for a rect
202
public:
203
    Degree100 m_nRotationAngle;
204
    Degree100 m_nShearAngle;
205
    double   mfTanShearAngle;      // tan(nShearAngle)
206
    double   mfSinRotationAngle;   // sin(nRotationAngle)
207
    double   mfCosRotationAngle;   // cos(nRotationAngle)
208
209
1.84M
    GeoStat(): m_nRotationAngle(0),m_nShearAngle(0),mfTanShearAngle(0.0),mfSinRotationAngle(0.0),mfCosRotationAngle(1.0) {}
210
    void RecalcSinCos();
211
    void RecalcTan();
212
};
213
214
tools::Polygon Rect2Poly(const tools::Rectangle& rRect, const GeoStat& rGeo);
215
216
namespace svx
217
{
218
tools::Rectangle polygonToRectangle(const tools::Polygon& rPolygon, GeoStat& rGeo);
219
}
220
221
void OrthoDistance8(const Point& rPt0, Point& rPt, bool bBigOrtho);
222
void OrthoDistance4(const Point& rPt0, Point& rPt, bool bBigOrtho);
223
224
// Multiplication and subsequent division
225
// Calculation and intermediate values are in BigInt
226
SVXCORE_DLLPUBLIC tools::Long BigMulDiv(tools::Long nVal, tools::Long nMul, tools::Long nDiv);
227
228
class FrPair {
229
    Fraction m_aX;
230
    Fraction m_aY;
231
public:
232
0
    FrPair(const Fraction& rBoth)                     : m_aX(rBoth),m_aY(rBoth)         {}
233
0
    FrPair(const Fraction& rX, const Fraction& rY)    : m_aX(rX),m_aY(rY)               {}
234
93.5k
    FrPair(tools::Long nMul, tools::Long nDiv)                      : m_aX(nMul,nDiv),m_aY(nMul,nDiv) {}
235
16.8k
    FrPair(tools::Long xMul, tools::Long xDiv, tools::Long yMul, tools::Long yDiv): m_aX(xMul,xDiv),m_aY(yMul,yDiv) {}
236
0
    const Fraction& X() const { return m_aX; }
237
0
    const Fraction& Y() const { return m_aY; }
238
110k
    Fraction& X()             { return m_aX; }
239
0
    Fraction& Y()             { return m_aY; }
240
};
241
242
// To convert units of measurement
243
SVXCORE_DLLPUBLIC FrPair GetMapFactor(MapUnit eS, MapUnit eD);
244
FrPair GetMapFactor(FieldUnit eS, FieldUnit eD);
245
246
0
inline bool IsMetric(MapUnit eU) {
247
0
    return (eU==MapUnit::Map100thMM || eU==MapUnit::Map10thMM || eU==MapUnit::MapMM || eU==MapUnit::MapCM);
248
0
}
249
250
99.8k
inline bool IsInch(MapUnit eU) {
251
99.8k
    return (eU==MapUnit::Map1000thInch || eU==MapUnit::Map100thInch || eU==MapUnit::Map10thInch || eU==MapUnit::MapInch ||
252
99.8k
            eU==MapUnit::MapPoint       || eU==MapUnit::MapTwip);
253
99.8k
}
254
255
0
inline bool IsMetric(FieldUnit eU) {
256
0
    return (eU == FieldUnit::MM || eU == FieldUnit::CM || eU == FieldUnit::M
257
0
            || eU == FieldUnit::KM || eU == FieldUnit::MM_100TH);
258
0
}
259
260
0
inline bool IsInch(FieldUnit eU) {
261
0
    return (eU == FieldUnit::TWIP || eU == FieldUnit::POINT
262
0
            || eU == FieldUnit::PICA || eU == FieldUnit::INCH
263
0
            || eU == FieldUnit::FOOT || eU == FieldUnit::MILE);
264
0
}
265
266
class SVXCORE_DLLPUBLIC SdrFormatter {
267
    tools::Long      m_nMul;
268
    tools::Long      m_nDiv;
269
    short     m_nComma;
270
    bool      m_bDirty;
271
    MapUnit   m_eSrcMU;
272
    MapUnit   m_eDstMU;
273
private:
274
    SVX_DLLPRIVATE void Undirty();
275
public:
276
    SdrFormatter(MapUnit eSrc, MapUnit eDst)
277
0
        : m_nMul(0)
278
0
        , m_nDiv(0)
279
0
        , m_nComma(0)
280
0
        , m_bDirty(true)
281
0
        , m_eSrcMU(eSrc)
282
0
        , m_eDstMU(eDst)
283
0
    {
284
0
    }
285
    OUString GetStr(tools::Long nVal) const;
286
    static OUString GetUnitStr(MapUnit eUnit);
287
    static OUString GetUnitStr(FieldUnit eUnit);
288
};
289
290
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */