summaryrefslogtreecommitdiff
path: root/include/tools/helpers.hxx
blob: 1d00bad7112e81df6e2e3e7c453fe1678cba5e87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
#ifndef INCLUDED_TOOLS_HELPERS_HXX
#define INCLUDED_TOOLS_HELPERS_HXX

#include <sal/config.h>
#include <sal/types.h>
#include <o3tl/safeint.hxx>
#include <cassert>
#include <type_traits>

template<typename T>
inline
typename std::enable_if<
             std::is_signed<T>::value || std::is_floating_point<T>::value, long >::type
MinMax(T nVal, long nMin, long nMax)
{
    assert(nMin <= nMax);
    if (nVal >= nMin)
    {
        if (nVal <= nMax)
            return static_cast<long>(nVal);
        else
           return nMax;
    }
    else
    {
        return nMin;
    }
}

template<typename T>
inline
typename std::enable_if<
             std::is_unsigned<T>::value, long >::type
MinMax(T nVal, long nMin, long nMax)
{
    assert(nMin <= nMax);
    if (nMax < 0)
    {
        return nMax;
    }
    else
    {
        if (nMin < 0 || nVal >= static_cast<unsigned long>(nMin))
        {
            if (nVal <= static_cast<unsigned long>(nMax))
                return static_cast<long>(nVal);
            else
                return nMax;
        }
        else
        {
            return nMin;
        }
    }
}

inline sal_uInt32 AlignedWidth4Bytes(sal_uInt32 nWidthBits)
{
    if (nWidthBits > SAL_MAX_UINT32 - 31)
        nWidthBits = SAL_MAX_UINT32;
    else
        nWidthBits += 31;
    return (nWidthBits >> 5) << 2;
}

inline long FRound( double fVal )
{
    return fVal > 0.0 ? static_cast<long>( fVal + 0.5 ) : -static_cast<long>( -fVal + 0.5 );
}

//valid range:  (-180,180]
template <typename T>
[[nodiscard]] inline typename std::enable_if<std::is_signed<T>::value, T>::type
NormAngle180(T angle)
{
    while (angle <= -180)
        angle += 360;
    while (angle > 180)
        angle -= 360;
    return angle;
}

//valid range:  [0,360)
template <typename T> [[nodiscard]] inline T NormAngle360(T angle)
{
    while (angle < 0)
        angle += 360;
    while (angle >= 360)
        angle -= 360;
    return angle;
}

/** Convert 100th-mm to twips

    A twip is 1/20 of a point, one inch is equal to 72 points, and
    one inch is 2,540 100th-mm.

    Thus:
        twips = n * 72 / 2,540 / 20
              = n * 72 / 127

    Adding 63 (half of 127) fixes truncation issues in int arithmetic.

    This formula is (n>=0) ? (n*72+63) / 127 : (n*72-63) / 127
 */
inline sal_Int64 sanitiseMm100ToTwip(sal_Int64 n)
{
    if (n >= 0)
    {
        if (o3tl::checked_multiply<sal_Int64>(n, 72, n) || o3tl::checked_add<sal_Int64>(n, 63, n))
            n = SAL_MAX_INT64;
    }
    else
    {
        if (o3tl::checked_multiply<sal_Int64>(n, 72, n) || o3tl::checked_sub<sal_Int64>(n, 63, n))
            n = SAL_MIN_INT64;
    }
    return n / 127; // 127 is 2,540 100th-mm divided by 20pts
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */