Bug 1157984 - Part 1: Extend gfx::2d classes to support both float and double precision,r=jrmuizel

- Implemented templates for Coord, Point, Point3D, Point4D, Size, Margin
  and Rect to create double precision versions.

--HG--
extra : rebase_source : 91e16a7b970026346b6e90a23427fd0f70491765
This commit is contained in:
"Kearwood \"Kip\" Gilbert" 2015-06-11 13:43:40 -07:00
Родитель 87aa5dec6e
Коммит 0f397fb78d
6 изменённых файлов: 104 добавлений и 79 удалений

Просмотреть файл

@ -7,6 +7,7 @@
#define MOZILLA_GFX_COORD_H_
#include "mozilla/Attributes.h"
#include "mozilla/TypeTraits.h" // For IsSame
#include "Types.h"
#include "BaseCoord.h"
@ -19,7 +20,7 @@ template <typename> struct IsPixel;
namespace gfx {
template <class units> struct IntCoordTyped;
template <class units> struct CoordTyped;
template <class units, class F = Float> struct CoordTyped;
// CommonType<coord, primitive> is a metafunction that returns the type of the
// result of an arithmetic operation on the underlying type of a strongly-typed
@ -37,9 +38,9 @@ struct CommonType<IntCoordTyped<units>, primitive> {
typedef decltype(int32_t() + primitive()) type;
};
template <class units, class primitive>
struct CommonType<CoordTyped<units>, primitive> {
typedef decltype(Float() + primitive()) type;
template <class units, class F, class primitive>
struct CommonType<CoordTyped<units, F>, primitive> {
typedef decltype(F() + primitive()) type;
};
// This is a base class that provides mixed-type operator overloads between
@ -48,8 +49,15 @@ struct CommonType<CoordTyped<units>, primitive> {
// convertible to their underlying value type. As we transition more of our code
// to strongly-typed classes, we may be able to remove some or all of these
// overloads.
template <class coord, class primitive>
template <bool B, class coord, class primitive>
struct CoordOperatorsHelper {
// Using SFINAE (Substitution Failure Is Not An Error) to suppress redundant
// operators
};
template <class coord, class primitive>
struct CoordOperatorsHelper<true, coord, primitive> {
friend bool operator==(coord aA, primitive aB) {
return aA.value == aB;
}
@ -95,8 +103,8 @@ struct CoordOperatorsHelper {
template<class units>
struct IntCoordTyped :
public BaseCoord< int32_t, IntCoordTyped<units> >,
public CoordOperatorsHelper< IntCoordTyped<units>, float >,
public CoordOperatorsHelper< IntCoordTyped<units>, double > {
public CoordOperatorsHelper< true, IntCoordTyped<units>, float >,
public CoordOperatorsHelper< true, IntCoordTyped<units>, double > {
static_assert(IsPixel<units>::value,
"'units' must be a coordinate system tag");
@ -106,20 +114,21 @@ struct IntCoordTyped :
MOZ_CONSTEXPR MOZ_IMPLICIT IntCoordTyped(int32_t aValue) : Super(aValue) {}
};
template<class units>
template<class units, class F>
struct CoordTyped :
public BaseCoord< Float, CoordTyped<units> >,
public CoordOperatorsHelper< CoordTyped<units>, int32_t >,
public CoordOperatorsHelper< CoordTyped<units>, uint32_t >,
public CoordOperatorsHelper< CoordTyped<units>, double > {
public BaseCoord< F, CoordTyped<units, F> >,
public CoordOperatorsHelper< !IsSame<F, int32_t>::value, CoordTyped<units, F>, int32_t >,
public CoordOperatorsHelper< !IsSame<F, uint32_t>::value, CoordTyped<units, F>, uint32_t >,
public CoordOperatorsHelper< !IsSame<F, double>::value, CoordTyped<units, F>, double >,
public CoordOperatorsHelper< !IsSame<F, float>::value, CoordTyped<units, F>, float > {
static_assert(IsPixel<units>::value,
"'units' must be a coordinate system tag");
typedef BaseCoord< Float, CoordTyped<units> > Super;
typedef BaseCoord< F, CoordTyped<units, F> > Super;
MOZ_CONSTEXPR CoordTyped() : Super() {}
MOZ_CONSTEXPR MOZ_IMPLICIT CoordTyped(Float aValue) : Super(aValue) {}
explicit MOZ_CONSTEXPR CoordTyped(const IntCoordTyped<units>& aCoord) : Super(float(aCoord.value)) {}
MOZ_CONSTEXPR MOZ_IMPLICIT CoordTyped(F aValue) : Super(aValue) {}
explicit MOZ_CONSTEXPR CoordTyped(const IntCoordTyped<units>& aCoord) : Super(F(aCoord.value)) {}
void Round() {
this->value = floor(this->value + 0.5);

Просмотреть файл

@ -64,37 +64,38 @@ struct IntPointTyped :
};
typedef IntPointTyped<UnknownUnits> IntPoint;
template<class units>
template<class units, class F = Float>
struct PointTyped :
public BasePoint< Float, PointTyped<units>, CoordTyped<units> >,
public BasePoint< F, PointTyped<units, F>, CoordTyped<units, F> >,
public units {
static_assert(IsPixel<units>::value,
"'units' must be a coordinate system tag");
typedef CoordTyped<units> Coord;
typedef BasePoint< Float, PointTyped<units>, CoordTyped<units> > Super;
typedef CoordTyped<units, F> Coord;
typedef BasePoint< F, PointTyped<units, F>, CoordTyped<units, F> > Super;
MOZ_CONSTEXPR PointTyped() : Super() {}
MOZ_CONSTEXPR PointTyped(Float aX, Float aY) : Super(Coord(aX), Coord(aY)) {}
MOZ_CONSTEXPR PointTyped(F aX, F aY) : Super(Coord(aX), Coord(aY)) {}
// The mixed-type constructors (Float, Coord) and (Coord, Float) are needed to
// avoid ambiguities because Coord is implicitly convertible to Float.
MOZ_CONSTEXPR PointTyped(Float aX, Coord aY) : Super(Coord(aX), aY) {}
MOZ_CONSTEXPR PointTyped(Coord aX, Float aY) : Super(aX, Coord(aY)) {}
MOZ_CONSTEXPR PointTyped(F aX, Coord aY) : Super(Coord(aX), aY) {}
MOZ_CONSTEXPR PointTyped(Coord aX, F aY) : Super(aX, Coord(aY)) {}
MOZ_CONSTEXPR PointTyped(Coord aX, Coord aY) : Super(aX.value, aY.value) {}
MOZ_CONSTEXPR MOZ_IMPLICIT PointTyped(const IntPointTyped<units>& point) : Super(float(point.x), float(point.y)) {}
MOZ_CONSTEXPR MOZ_IMPLICIT PointTyped(const IntPointTyped<units>& point) : Super(F(point.x), F(point.y)) {}
// XXX When all of the code is ported, the following functions to convert to and from
// unknown types should be removed.
static PointTyped<units> FromUnknownPoint(const PointTyped<UnknownUnits>& aPoint) {
return PointTyped<units>(aPoint.x, aPoint.y);
static PointTyped<units, F> FromUnknownPoint(const PointTyped<UnknownUnits, F>& aPoint) {
return PointTyped<units, F>(aPoint.x, aPoint.y);
}
PointTyped<UnknownUnits> ToUnknownPoint() const {
return PointTyped<UnknownUnits>(this->x, this->y);
PointTyped<UnknownUnits, F> ToUnknownPoint() const {
return PointTyped<UnknownUnits, F>(this->x, this->y);
}
};
typedef PointTyped<UnknownUnits> Point;
typedef PointTyped<UnknownUnits, double> PointDouble;
template<class units>
IntPointTyped<units> RoundedToInt(const PointTyped<units>& aPoint) {
@ -108,57 +109,59 @@ IntPointTyped<units> TruncatedToInt(const PointTyped<units>& aPoint) {
int32_t(aPoint.y));
}
template<class units>
template<class units, class F = Float>
struct Point3DTyped :
public BasePoint3D< Float, Point3DTyped<units> > {
public BasePoint3D< F, Point3DTyped<units, F> > {
static_assert(IsPixel<units>::value,
"'units' must be a coordinate system tag");
typedef BasePoint3D< Float, Point3DTyped<units> > Super;
typedef BasePoint3D< F, Point3DTyped<units, F> > Super;
Point3DTyped() : Super() {}
Point3DTyped(Float aX, Float aY, Float aZ) : Super(aX, aY, aZ) {}
Point3DTyped(F aX, F aY, F aZ) : Super(aX, aY, aZ) {}
// XXX When all of the code is ported, the following functions to convert to and from
// unknown types should be removed.
static Point3DTyped<units> FromUnknownPoint(const Point3DTyped<UnknownUnits>& aPoint) {
return Point3DTyped<units>(aPoint.x, aPoint.y, aPoint.z);
static Point3DTyped<units, F> FromUnknownPoint(const Point3DTyped<UnknownUnits, F>& aPoint) {
return Point3DTyped<units, F>(aPoint.x, aPoint.y, aPoint.z);
}
Point3DTyped<UnknownUnits> ToUnknownPoint() const {
return Point3DTyped<UnknownUnits>(this->x, this->y, this->z);
Point3DTyped<UnknownUnits, F> ToUnknownPoint() const {
return Point3DTyped<UnknownUnits, F>(this->x, this->y, this->z);
}
};
typedef Point3DTyped<UnknownUnits> Point3D;
typedef Point3DTyped<UnknownUnits, double> PointDouble3D;
template<class units>
template<class units, class F = Float>
struct Point4DTyped :
public BasePoint4D< Float, Point4DTyped<units> > {
public BasePoint4D< F, Point4DTyped<units, F> > {
static_assert(IsPixel<units>::value,
"'units' must be a coordinate system tag");
typedef BasePoint4D< Float, Point4DTyped<units> > Super;
typedef BasePoint4D< F, Point4DTyped<units, F> > Super;
Point4DTyped() : Super() {}
Point4DTyped(Float aX, Float aY, Float aZ, Float aW) : Super(aX, aY, aZ, aW) {}
Point4DTyped(F aX, F aY, F aZ, F aW) : Super(aX, aY, aZ, aW) {}
// XXX When all of the code is ported, the following functions to convert to and from
// unknown types should be removed.
static Point4DTyped<units> FromUnknownPoint(const Point4DTyped<UnknownUnits>& aPoint) {
return Point4DTyped<units>(aPoint.x, aPoint.y, aPoint.z, aPoint.w);
static Point4DTyped<units, F> FromUnknownPoint(const Point4DTyped<UnknownUnits, F>& aPoint) {
return Point4DTyped<units, F>(aPoint.x, aPoint.y, aPoint.z, aPoint.w);
}
Point4DTyped<UnknownUnits> ToUnknownPoint() const {
return Point4DTyped<UnknownUnits>(this->x, this->y, this->z, this->w);
Point4DTyped<UnknownUnits, F> ToUnknownPoint() const {
return Point4DTyped<UnknownUnits, F>(this->x, this->y, this->z, this->w);
}
PointTyped<units> As2DPoint() {
return PointTyped<units>(this->x / this->w, this->y / this->w);
PointTyped<units, F> As2DPoint() {
return PointTyped<units, F>(this->x / this->w, this->y / this->w);
}
};
typedef Point4DTyped<UnknownUnits> Point4D;
typedef Point4DTyped<UnknownUnits, double> PointDouble4D;
template<class units>
struct IntSizeTyped :
@ -185,32 +188,33 @@ struct IntSizeTyped :
};
typedef IntSizeTyped<UnknownUnits> IntSize;
template<class units>
template<class units, class F = Float>
struct SizeTyped :
public BaseSize< Float, SizeTyped<units> >,
public BaseSize< F, SizeTyped<units> >,
public units {
static_assert(IsPixel<units>::value,
"'units' must be a coordinate system tag");
typedef BaseSize< Float, SizeTyped<units> > Super;
typedef BaseSize< F, SizeTyped<units, F> > Super;
MOZ_CONSTEXPR SizeTyped() : Super() {}
MOZ_CONSTEXPR SizeTyped(Float aWidth, Float aHeight) : Super(aWidth, aHeight) {}
MOZ_CONSTEXPR SizeTyped(F aWidth, F aHeight) : Super(aWidth, aHeight) {}
explicit SizeTyped(const IntSizeTyped<units>& size) :
Super(float(size.width), float(size.height)) {}
Super(F(size.width), F(size.height)) {}
// XXX When all of the code is ported, the following functions to convert to and from
// unknown types should be removed.
static SizeTyped<units> FromUnknownSize(const SizeTyped<UnknownUnits>& aSize) {
return SizeTyped<units>(aSize.width, aSize.height);
static SizeTyped<units, F> FromUnknownSize(const SizeTyped<UnknownUnits, F>& aSize) {
return SizeTyped<units, F>(aSize.width, aSize.height);
}
SizeTyped<UnknownUnits> ToUnknownSize() const {
return SizeTyped<UnknownUnits>(this->width, this->height);
SizeTyped<UnknownUnits, F> ToUnknownSize() const {
return SizeTyped<UnknownUnits, F>(this->width, this->height);
}
};
typedef SizeTyped<UnknownUnits> Size;
typedef SizeTyped<UnknownUnits, double> SizeDouble;
template<class units>
IntSizeTyped<units> RoundedToInt(const SizeTyped<units>& aSize) {

Просмотреть файл

@ -35,23 +35,24 @@ struct IntMarginTyped:
};
typedef IntMarginTyped<UnknownUnits> IntMargin;
template<class units>
template<class units, class F = Float>
struct MarginTyped:
public BaseMargin<Float, MarginTyped<units> >,
public BaseMargin<F, MarginTyped<units> >,
public units {
static_assert(IsPixel<units>::value,
"'units' must be a coordinate system tag");
typedef BaseMargin<Float, MarginTyped<units> > Super;
typedef BaseMargin<F, MarginTyped<units, F> > Super;
MarginTyped() : Super() {}
MarginTyped(Float aTop, Float aRight, Float aBottom, Float aLeft) :
MarginTyped(F aTop, F aRight, F aBottom, F aLeft) :
Super(aTop, aRight, aBottom, aLeft) {}
explicit MarginTyped(const IntMarginTyped<units>& aMargin) :
Super(float(aMargin.top), float(aMargin.right),
float(aMargin.bottom), float(aMargin.left)) {}
Super(F(aMargin.top), F(aMargin.right),
F(aMargin.bottom), F(aMargin.left)) {}
};
typedef MarginTyped<UnknownUnits> Margin;
typedef MarginTyped<UnknownUnits, double> MarginDouble;
template<class units>
IntMarginTyped<units> RoundedToInt(const MarginTyped<units>& aMargin)
@ -124,23 +125,23 @@ struct IntRectTyped :
};
typedef IntRectTyped<UnknownUnits> IntRect;
template<class units>
template<class units, class F = Float>
struct RectTyped :
public BaseRect<Float, RectTyped<units>, PointTyped<units>, SizeTyped<units>, MarginTyped<units> >,
public BaseRect<F, RectTyped<units, F>, PointTyped<units, F>, SizeTyped<units, F>, MarginTyped<units, F> >,
public units {
static_assert(IsPixel<units>::value,
"'units' must be a coordinate system tag");
typedef BaseRect<Float, RectTyped<units>, PointTyped<units>, SizeTyped<units>, MarginTyped<units> > Super;
typedef BaseRect<F, RectTyped<units, F>, PointTyped<units, F>, SizeTyped<units, F>, MarginTyped<units, F> > Super;
RectTyped() : Super() {}
RectTyped(const PointTyped<units>& aPos, const SizeTyped<units>& aSize) :
RectTyped(const PointTyped<units, F>& aPos, const SizeTyped<units, F>& aSize) :
Super(aPos, aSize) {}
RectTyped(Float _x, Float _y, Float _width, Float _height) :
RectTyped(F _x, F _y, F _width, F _height) :
Super(_x, _y, _width, _height) {}
explicit RectTyped(const IntRectTyped<units>& rect) :
Super(float(rect.x), float(rect.y),
float(rect.width), float(rect.height)) {}
Super(F(rect.x), F(rect.y),
F(rect.width), F(rect.height)) {}
void NudgeToIntegers()
{
@ -154,29 +155,30 @@ struct RectTyped :
{
*aOut = IntRectTyped<units>(int32_t(this->X()), int32_t(this->Y()),
int32_t(this->Width()), int32_t(this->Height()));
return RectTyped<units>(Float(aOut->x), Float(aOut->y),
Float(aOut->width), Float(aOut->height))
return RectTyped<units>(F(aOut->x), F(aOut->y),
F(aOut->width), F(aOut->height))
.IsEqualEdges(*this);
}
// XXX When all of the code is ported, the following functions to convert to and from
// unknown types should be removed.
static RectTyped<units> FromUnknownRect(const RectTyped<UnknownUnits>& rect) {
return RectTyped<units>(rect.x, rect.y, rect.width, rect.height);
static RectTyped<units, F> FromUnknownRect(const RectTyped<UnknownUnits, F>& rect) {
return RectTyped<units, F>(rect.x, rect.y, rect.width, rect.height);
}
RectTyped<UnknownUnits> ToUnknownRect() const {
return RectTyped<UnknownUnits>(this->x, this->y, this->width, this->height);
RectTyped<UnknownUnits, F> ToUnknownRect() const {
return RectTyped<UnknownUnits, F>(this->x, this->y, this->width, this->height);
}
// This is here only to keep IPDL-generated code happy. DO NOT USE.
bool operator==(const RectTyped<units>& aRect) const
bool operator==(const RectTyped<units, F>& aRect) const
{
return RectTyped<units>::IsEqualEdges(aRect);
return RectTyped<units, F>::IsEqualEdges(aRect);
}
};
typedef RectTyped<UnknownUnits> Rect;
typedef RectTyped<UnknownUnits, double> RectDouble;
template<class units>
IntRectTyped<units> RoundedToInt(const RectTyped<units>& aRect)

Просмотреть файл

@ -527,10 +527,10 @@ struct ParamTraits< mozilla::gfx::PointTyped<T> >
}
};
template<class T>
struct ParamTraits< mozilla::gfx::Point3DTyped<T> >
template<class F, class T>
struct ParamTraits< mozilla::gfx::Point3DTyped<F, T> >
{
typedef mozilla::gfx::Point3DTyped<T> paramType;
typedef mozilla::gfx::Point3DTyped<F, T> paramType;
static void Write(Message* msg, const paramType& param)
{

Просмотреть файл

@ -21,7 +21,7 @@ struct gfxRGBA;
namespace mozilla {
namespace gfx {
class Matrix4x4;
template <class units> struct RectTyped;
template <class units, class F> struct RectTyped;
} // namespace gfx
enum class ImageFormat;

Просмотреть файл

@ -24,6 +24,11 @@ inline Rect ToRect(const gfxRect &aRect)
Float(aRect.width), Float(aRect.height));
}
inline RectDouble ToRectDouble(const gfxRect &aRect)
{
return RectDouble(aRect.x, aRect.y, aRect.width, aRect.height);
}
inline Rect ToRect(const IntRect &aRect)
{
return Rect(aRect.x, aRect.y, aRect.width, aRect.height);
@ -143,6 +148,11 @@ inline gfxRect ThebesRect(const Rect &aRect)
return gfxRect(aRect.x, aRect.y, aRect.width, aRect.height);
}
inline gfxRect ThebesRect(const RectDouble &aRect)
{
return gfxRect(aRect.x, aRect.y, aRect.width, aRect.height);
}
inline gfxRGBA ThebesRGBA(const Color &aColor)
{
return gfxRGBA(aColor.r, aColor.g, aColor.b, aColor.a);