Bug 1299741 part 5 - Move FastDivideBy255 into gfx/Tools.h and replace the macro in nsColor.h with it. r?jrmuizel
MozReview-Commit-ID: G3OYNHHawh4
--- a/gfx/2d/SIMD.h
+++ b/gfx/2d/SIMD.h
@@ -660,48 +660,36 @@ PackAndSaturate16To8(Scalari16x8_t m1, S
m.u8[11] = SaturateTo8(m2.i16[3]);
m.u8[12] = SaturateTo8(m2.i16[4]);
m.u8[13] = SaturateTo8(m2.i16[5]);
m.u8[14] = SaturateTo8(m2.i16[6]);
m.u8[15] = SaturateTo8(m2.i16[7]);
return m;
}
-// Fast approximate division by 255. It has the property that
-// for all 0 <= n <= 255*255, FAST_DIVIDE_BY_255(n) == n/255.
-// But it only uses two adds and two shifts instead of an
-// integer division (which is expensive on many processors).
-//
-// equivalent to v/255
-template<class B, class A>
-inline B FastDivideBy255(A v)
-{
- return ((v << 8) + v + 255) >> 16;
-}
-
inline Scalaru16x8_t
FastDivideBy255_16(Scalaru16x8_t m)
{
- return FromU16<Scalaru16x8_t>(FastDivideBy255<uint16_t>(int32_t(m.u16[0])),
- FastDivideBy255<uint16_t>(int32_t(m.u16[1])),
- FastDivideBy255<uint16_t>(int32_t(m.u16[2])),
- FastDivideBy255<uint16_t>(int32_t(m.u16[3])),
- FastDivideBy255<uint16_t>(int32_t(m.u16[4])),
- FastDivideBy255<uint16_t>(int32_t(m.u16[5])),
- FastDivideBy255<uint16_t>(int32_t(m.u16[6])),
- FastDivideBy255<uint16_t>(int32_t(m.u16[7])));
+ return FromU16<Scalaru16x8_t>(uint16_t(FastDivideBy255(int32_t(m.u16[0]))),
+ uint16_t(FastDivideBy255(int32_t(m.u16[1]))),
+ uint16_t(FastDivideBy255(int32_t(m.u16[2]))),
+ uint16_t(FastDivideBy255(int32_t(m.u16[3]))),
+ uint16_t(FastDivideBy255(int32_t(m.u16[4]))),
+ uint16_t(FastDivideBy255(int32_t(m.u16[5]))),
+ uint16_t(FastDivideBy255(int32_t(m.u16[6]))),
+ uint16_t(FastDivideBy255(int32_t(m.u16[7]))));
}
inline Scalari32x4_t
FastDivideBy255(Scalari32x4_t m)
{
- return From32<Scalari32x4_t>(FastDivideBy255<int32_t>(m.i32[0]),
- FastDivideBy255<int32_t>(m.i32[1]),
- FastDivideBy255<int32_t>(m.i32[2]),
- FastDivideBy255<int32_t>(m.i32[3]));
+ return From32<Scalari32x4_t>(gfx::FastDivideBy255(m.i32[0]),
+ gfx::FastDivideBy255(m.i32[1]),
+ gfx::FastDivideBy255(m.i32[2]),
+ gfx::FastDivideBy255(m.i32[3]));
}
inline Scalaru8x16_t
Pick(Scalaru8x16_t mask, Scalaru8x16_t a, Scalaru8x16_t b)
{
return From8<Scalaru8x16_t>((a.u8[0] & (~mask.u8[0])) | (b.u8[0] & mask.u8[0]),
(a.u8[1] & (~mask.u8[1])) | (b.u8[1] & mask.u8[1]),
(a.u8[2] & (~mask.u8[2])) | (b.u8[2] & mask.u8[2]),
--- a/gfx/2d/Tools.h
+++ b/gfx/2d/Tools.h
@@ -7,16 +7,17 @@
#define MOZILLA_GFX_TOOLS_H_
#include "mozilla/CheckedInt.h"
#include "mozilla/Move.h"
#include "mozilla/TypeTraits.h"
#include "Types.h"
#include "Point.h"
#include <math.h>
+#include <limits>
namespace mozilla {
namespace gfx {
static inline bool
IsOperatorBoundByMask(CompositionOp aOp) {
switch (aOp) {
case CompositionOp::OP_IN:
@@ -235,12 +236,29 @@ int32_t GetAlignedStride(int32_t aWidth,
const int32_t mask = alignment - 1;
CheckedInt32 stride = CheckedInt32(aWidth) * CheckedInt32(aBytesPerPixel) + CheckedInt32(mask);
if (stride.isValid()) {
return stride.value() & ~mask;
}
return 0;
}
+// Fast approximate division by 255. It has the property that
+// for all 0 <= n <= 255*255, FastDivideBy255(n) == n/255.
+// But it only uses two adds and two shifts instead of an
+// integer division (which is expensive on many processors).
+//
+// equivalent to v/255
+template<typename T>
+inline T FastDivideBy255(T v)
+{
+ // If v = 255*255, the maximum intermediate value would be
+ // 255*255*256 + 255*255 + 255 = 255*256*256, so any type cannot
+ // store 255 << 16 is definitely not suitable here.
+ static_assert(std::numeric_limits<T>::max() >= 255 << 16,
+ "Given type may not enough for intermediate value");
+ return ((v << 8) + v + 255) >> 16;
+}
+
} // namespace gfx
} // namespace mozilla
#endif /* MOZILLA_GFX_TOOLS_H_ */
--- a/gfx/src/nsColor.cpp
+++ b/gfx/src/nsColor.cpp
@@ -1,25 +1,27 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "mozilla/ArrayUtils.h" // for ArrayLength
#include "mozilla/mozalloc.h" // for operator delete, etc
+#include "mozilla/gfx/Tools.h" // for FastDivideBy255
#include "nsColor.h"
#include <sys/types.h> // for int32_t
#include "nsColorNames.h" // for nsColorNames
#include "nsDebug.h" // for NS_ASSERTION, etc
#include "nsStaticNameTable.h"
#include "nsString.h" // for nsAutoCString, nsString, etc
#include "nscore.h" // for nsAString, etc
using namespace mozilla;
+using namespace mozilla::gfx;
// define an array of all color names
#define GFX_COLOR(_name, _value) #_name,
static const char* const kColorNames[] = {
#include "nsColorNameList.h"
};
#undef GFX_COLOR
@@ -217,47 +219,45 @@ bool NS_ColorNameToRGB(const nsAString&
// Returns kColorNames, an array of all possible color names, and sets
// *aSizeArray to the size of that array. Do NOT call free() on this array.
const char * const * NS_AllColorNames(size_t *aSizeArray)
{
*aSizeArray = ArrayLength(kColorNames);
return kColorNames;
}
-// Macro to blend two colors
-//
-// equivalent to target = (bg*(255-fgalpha) + fg*fgalpha)/255
-#define MOZ_BLEND(target, bg, fg, fgalpha) \
- FAST_DIVIDE_BY_255(target, (bg)*(255-fgalpha) + (fg)*(fgalpha))
+// Function to blend two colors
+// equivalent to (bg*(255-fgalpha) + fg*fgalpha)/255
+static uint32_t
+BlendColorComponent(uint32_t aBg, uint32_t aFg, uint32_t aFgAlpha)
+{
+ return FastDivideBy255(aBg * (255 - aFgAlpha) + aFg * aFgAlpha);
+}
nscolor
NS_ComposeColors(nscolor aBG, nscolor aFG)
{
// This function uses colors that are non premultiplied alpha.
- int r, g, b, a;
-
int bgAlpha = NS_GET_A(aBG);
int fgAlpha = NS_GET_A(aFG);
// Compute the final alpha of the blended color
// a = fgAlpha + bgAlpha*(255 - fgAlpha)/255;
- FAST_DIVIDE_BY_255(a, bgAlpha*(255-fgAlpha));
- a = fgAlpha + a;
+ auto a = fgAlpha + FastDivideBy255(bgAlpha * (255 - fgAlpha));
int blendAlpha;
if (a == 0) {
// In this case the blended color is totally trasparent,
// we preserve the color information of the foreground color.
blendAlpha = 255;
} else {
blendAlpha = (fgAlpha*255)/a;
}
- MOZ_BLEND(r, NS_GET_R(aBG), NS_GET_R(aFG), blendAlpha);
- MOZ_BLEND(g, NS_GET_G(aBG), NS_GET_G(aFG), blendAlpha);
- MOZ_BLEND(b, NS_GET_B(aBG), NS_GET_B(aFG), blendAlpha);
-
+ auto r = BlendColorComponent(NS_GET_R(aBG), NS_GET_R(aFG), blendAlpha);
+ auto g = BlendColorComponent(NS_GET_G(aBG), NS_GET_G(aFG), blendAlpha);
+ auto b = BlendColorComponent(NS_GET_B(aBG), NS_GET_B(aFG), blendAlpha);
return NS_RGBA(r, g, b, a);
}
// Functions to convert from HSL color space to RGB color space.
// This is the algorithm described in the CSS3 specification
// helper
static float
--- a/gfx/src/nsColor.h
+++ b/gfx/src/nsColor.h
@@ -41,28 +41,16 @@ inline uint_fast8_t NS_ClampColor(T aCol
return 255;
}
if (aColor <= 0) {
return 0;
}
return NSToIntRound(aColor);
}
-// Fast approximate division by 255. It has the property that
-// for all 0 <= n <= 255*255, FAST_DIVIDE_BY_255(n) == n/255.
-// But it only uses two adds and two shifts instead of an
-// integer division (which is expensive on many processors).
-//
-// equivalent to target=v/255
-#define FAST_DIVIDE_BY_255(target,v) \
- PR_BEGIN_MACRO \
- unsigned tmp_ = v; \
- target = ((tmp_ << 8) + tmp_ + 255) >> 16; \
- PR_END_MACRO
-
enum class nsHexColorType : uint8_t {
NoAlpha, // 3 or 6 digit hex colors only
AllowAlpha, // 3, 4, 6, or 8 digit hex colors
};
// Translate a hex string to a color. Return true if it parses ok,
// otherwise return false.
// This accepts the number of digits specified by aType.