|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef MOZILLA_GFX_TOOLS_H_ |
|
7 #define MOZILLA_GFX_TOOLS_H_ |
|
8 |
|
9 #include "Types.h" |
|
10 #include "Point.h" |
|
11 #include <math.h> |
|
12 #if defined(_MSC_VER) && (_MSC_VER < 1600) |
|
13 #define hypotf _hypotf |
|
14 #endif |
|
15 |
|
16 namespace mozilla { |
|
17 namespace gfx { |
|
18 |
|
19 static inline bool |
|
20 IsOperatorBoundByMask(CompositionOp aOp) { |
|
21 switch (aOp) { |
|
22 case CompositionOp::OP_IN: |
|
23 case CompositionOp::OP_OUT: |
|
24 case CompositionOp::OP_DEST_IN: |
|
25 case CompositionOp::OP_DEST_ATOP: |
|
26 case CompositionOp::OP_SOURCE: |
|
27 return false; |
|
28 default: |
|
29 return true; |
|
30 } |
|
31 } |
|
32 |
|
33 template <class T> |
|
34 struct ClassStorage |
|
35 { |
|
36 char bytes[sizeof(T)]; |
|
37 |
|
38 const T *addr() const { return (const T *)bytes; } |
|
39 T *addr() { return (T *)(void *)bytes; } |
|
40 }; |
|
41 |
|
42 static inline bool |
|
43 FuzzyEqual(Float aA, Float aB, Float aErr) |
|
44 { |
|
45 if ((aA + aErr >= aB) && (aA - aErr <= aB)) { |
|
46 return true; |
|
47 } |
|
48 return false; |
|
49 } |
|
50 |
|
51 static inline void |
|
52 NudgeToInteger(float *aVal) |
|
53 { |
|
54 float r = floorf(*aVal + 0.5f); |
|
55 // The error threshold should be proportional to the rounded value. This |
|
56 // bounds the relative error introduced by the nudge operation. However, |
|
57 // when the rounded value is 0, the error threshold can't be proportional |
|
58 // to the rounded value (we'd never round), so we just choose the same |
|
59 // threshold as for a rounded value of 1. |
|
60 if (FuzzyEqual(r, *aVal, r == 0.0f ? 1e-6f : fabs(r*1e-6f))) { |
|
61 *aVal = r; |
|
62 } |
|
63 } |
|
64 |
|
65 static inline Float |
|
66 Distance(Point aA, Point aB) |
|
67 { |
|
68 return hypotf(aB.x - aA.x, aB.y - aA.y); |
|
69 } |
|
70 |
|
71 static inline int |
|
72 BytesPerPixel(SurfaceFormat aFormat) |
|
73 { |
|
74 switch (aFormat) { |
|
75 case SurfaceFormat::A8: |
|
76 return 1; |
|
77 case SurfaceFormat::R5G6B5: |
|
78 return 2; |
|
79 default: |
|
80 return 4; |
|
81 } |
|
82 } |
|
83 |
|
84 template<typename T, int alignment = 16> |
|
85 struct AlignedArray |
|
86 { |
|
87 AlignedArray() |
|
88 : mStorage(nullptr) |
|
89 , mPtr(nullptr) |
|
90 { |
|
91 } |
|
92 |
|
93 MOZ_ALWAYS_INLINE AlignedArray(size_t aSize) |
|
94 : mStorage(nullptr) |
|
95 { |
|
96 Realloc(aSize); |
|
97 } |
|
98 |
|
99 MOZ_ALWAYS_INLINE ~AlignedArray() |
|
100 { |
|
101 delete [] mStorage; |
|
102 } |
|
103 |
|
104 void Dealloc() |
|
105 { |
|
106 delete [] mStorage; |
|
107 mStorage = mPtr = nullptr; |
|
108 } |
|
109 |
|
110 MOZ_ALWAYS_INLINE void Realloc(size_t aSize) |
|
111 { |
|
112 delete [] mStorage; |
|
113 mStorage = new (std::nothrow) T[aSize + (alignment - 1)]; |
|
114 if (uintptr_t(mStorage) % alignment) { |
|
115 // Our storage does not start at a <alignment>-byte boundary. Make sure mData does! |
|
116 mPtr = (T*)(uintptr_t(mStorage) + |
|
117 (alignment - (uintptr_t(mStorage) % alignment))); |
|
118 } else { |
|
119 mPtr = mStorage; |
|
120 } |
|
121 } |
|
122 |
|
123 MOZ_ALWAYS_INLINE operator T*() |
|
124 { |
|
125 return mPtr; |
|
126 } |
|
127 |
|
128 T *mStorage; |
|
129 T *mPtr; |
|
130 }; |
|
131 |
|
132 template<int alignment> |
|
133 int32_t GetAlignedStride(int32_t aStride) |
|
134 { |
|
135 if (aStride % alignment) { |
|
136 return aStride + (alignment - (aStride % alignment)); |
|
137 } |
|
138 |
|
139 return aStride; |
|
140 } |
|
141 |
|
142 } |
|
143 } |
|
144 |
|
145 #endif /* MOZILLA_GFX_TOOLS_H_ */ |