mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 1255632 - Make Maybe::map and Maybe::apply support lambdas. r=waldo,njn
This commit is contained in:
parent
172d673bcc
commit
358b410aaa
@ -405,24 +405,6 @@ ClippedImage::Draw(gfxContext* aContext,
|
||||
aSamplingFilter, aSVGContext, aFlags);
|
||||
}
|
||||
|
||||
static SVGImageContext
|
||||
UnclipViewport(const SVGImageContext& aOldContext,
|
||||
const pair<nsIntSize, nsIntSize>& aInnerAndClipSize)
|
||||
{
|
||||
nsIntSize innerSize(aInnerAndClipSize.first);
|
||||
nsIntSize clipSize(aInnerAndClipSize.second);
|
||||
|
||||
// Map the viewport to the inner image. (Note that we don't take the aSize
|
||||
// parameter of Draw into account, just the clipping region.)
|
||||
CSSIntSize vSize(aOldContext.GetViewportSize());
|
||||
vSize.width = ceil(vSize.width * double(innerSize.width) / clipSize.width);
|
||||
vSize.height =
|
||||
ceil(vSize.height * double(innerSize.height) / clipSize.height);
|
||||
|
||||
return SVGImageContext(vSize,
|
||||
aOldContext.GetPreserveAspectRatio());
|
||||
}
|
||||
|
||||
DrawResult
|
||||
ClippedImage::DrawSingleTile(gfxContext* aContext,
|
||||
const nsIntSize& aSize,
|
||||
@ -468,10 +450,24 @@ ClippedImage::DrawSingleTile(gfxContext* aContext,
|
||||
gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
|
||||
aContext->Multiply(gfxMatrix::Translation(-clip.x, -clip.y));
|
||||
|
||||
auto unclipViewport = [&](const SVGImageContext& aOldContext) {
|
||||
// Map the viewport to the inner image. Note that we don't take the aSize
|
||||
// parameter of imgIContainer::Draw into account, just the clipping region.
|
||||
// The size in pixels at which the output will ultimately be drawn is
|
||||
// irrelevant here since the purpose of the SVG viewport size is to
|
||||
// determine what *region* of the SVG document will be drawn.
|
||||
CSSIntSize vSize(aOldContext.GetViewportSize());
|
||||
vSize.width = ceil(vSize.width * double(innerSize.width) / mClip.width);
|
||||
vSize.height =
|
||||
ceil(vSize.height * double(innerSize.height) / mClip.height);
|
||||
|
||||
return SVGImageContext(vSize,
|
||||
aOldContext.GetPreserveAspectRatio());
|
||||
};
|
||||
|
||||
return InnerImage()->Draw(aContext, size, region,
|
||||
aWhichFrame, aSamplingFilter,
|
||||
aSVGContext.map(UnclipViewport,
|
||||
make_pair(innerSize, mClip.Size())),
|
||||
aSVGContext.map(unclipViewport),
|
||||
aFlags);
|
||||
}
|
||||
|
||||
|
@ -256,18 +256,6 @@ OrientedImage::OrientationMatrix(const nsIntSize& aSize,
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
static SVGImageContext
|
||||
OrientViewport(const SVGImageContext& aOldContext,
|
||||
const Orientation& aOrientation)
|
||||
{
|
||||
CSSIntSize viewportSize(aOldContext.GetViewportSize());
|
||||
if (aOrientation.SwapsWidthAndHeight()) {
|
||||
swap(viewportSize.width, viewportSize.height);
|
||||
}
|
||||
return SVGImageContext(viewportSize,
|
||||
aOldContext.GetPreserveAspectRatio());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(DrawResult)
|
||||
OrientedImage::Draw(gfxContext* aContext,
|
||||
const nsIntSize& aSize,
|
||||
@ -303,9 +291,17 @@ OrientedImage::Draw(gfxContext* aContext,
|
||||
ImageRegion region(aRegion);
|
||||
region.TransformBoundsBy(inverseMatrix);
|
||||
|
||||
auto orientViewport = [&](const SVGImageContext& aOldContext) {
|
||||
CSSIntSize viewportSize(aOldContext.GetViewportSize());
|
||||
if (mOrientation.SwapsWidthAndHeight()) {
|
||||
swap(viewportSize.width, viewportSize.height);
|
||||
}
|
||||
return SVGImageContext(viewportSize,
|
||||
aOldContext.GetPreserveAspectRatio());
|
||||
};
|
||||
|
||||
return InnerImage()->Draw(aContext, size, region, aWhichFrame, aSamplingFilter,
|
||||
aSVGContext.map(OrientViewport, mOrientation),
|
||||
aFlags);
|
||||
aSVGContext.map(orientViewport), aFlags);
|
||||
}
|
||||
|
||||
nsIntSize
|
||||
|
36
mfbt/Maybe.h
36
mfbt/Maybe.h
@ -324,46 +324,50 @@ public:
|
||||
|
||||
/* If |isSome()|, runs the provided function or functor on the contents of
|
||||
* this Maybe. */
|
||||
template<typename F, typename... Args>
|
||||
void apply(F&& aFunc, Args&&... aArgs)
|
||||
template<typename Func>
|
||||
Maybe& apply(Func aFunc)
|
||||
{
|
||||
if (isSome()) {
|
||||
aFunc(ref(), Forward<Args>(aArgs)...);
|
||||
aFunc(ref());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename F, typename... Args>
|
||||
void apply(F&& aFunc, Args&&... aArgs) const
|
||||
template<typename Func>
|
||||
const Maybe& apply(Func aFunc) const
|
||||
{
|
||||
if (isSome()) {
|
||||
aFunc(ref(), Forward<Args>(aArgs)...);
|
||||
aFunc(ref());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* If |isSome()|, runs the provided function and returns the result wrapped
|
||||
* in a Maybe. If |isNothing()|, returns an empty Maybe value.
|
||||
*/
|
||||
template<typename R, typename... FArgs, typename... Args>
|
||||
Maybe<R> map(R (*aFunc)(T&, FArgs...), Args&&... aArgs)
|
||||
template<typename Func>
|
||||
auto map(Func aFunc) -> Maybe<decltype(aFunc(ref()))>
|
||||
{
|
||||
using ReturnType = decltype(aFunc(ref()));
|
||||
if (isSome()) {
|
||||
Maybe<R> val;
|
||||
val.emplace(aFunc(ref(), Forward<Args>(aArgs)...));
|
||||
Maybe<ReturnType> val;
|
||||
val.emplace(aFunc(ref()));
|
||||
return val;
|
||||
}
|
||||
return Maybe<R>();
|
||||
return Maybe<ReturnType>();
|
||||
}
|
||||
|
||||
template<typename R, typename... FArgs, typename... Args>
|
||||
Maybe<R> map(R (*aFunc)(const T&, FArgs...), Args&&... aArgs) const
|
||||
template<typename Func>
|
||||
auto map(Func aFunc) const -> Maybe<decltype(aFunc(ref()))>
|
||||
{
|
||||
using ReturnType = decltype(aFunc(ref()));
|
||||
if (isSome()) {
|
||||
Maybe<R> val;
|
||||
val.emplace(aFunc(ref(), Forward<Args>(aArgs)...));
|
||||
Maybe<ReturnType> val;
|
||||
val.emplace(aFunc(ref()));
|
||||
return val;
|
||||
}
|
||||
return Maybe<R>();
|
||||
return Maybe<ReturnType>();
|
||||
}
|
||||
|
||||
/* If |isSome()|, empties this Maybe and destroys its contents. */
|
||||
|
@ -526,48 +526,22 @@ IncrementTag(BasicValue& aValue)
|
||||
aValue.SetTag(aValue.GetTag() + 1);
|
||||
}
|
||||
|
||||
static void
|
||||
IncrementTagBy(BasicValue& aValue, int aAmount)
|
||||
{
|
||||
gFunctionWasApplied = true;
|
||||
aValue.SetTag(aValue.GetTag() + aAmount);
|
||||
}
|
||||
|
||||
static void
|
||||
AccessValue(const BasicValue&)
|
||||
{
|
||||
gFunctionWasApplied = true;
|
||||
}
|
||||
|
||||
static void
|
||||
AccessValueWithArg(const BasicValue&, int)
|
||||
{
|
||||
gFunctionWasApplied = true;
|
||||
}
|
||||
|
||||
struct IncrementTagFunctor
|
||||
{
|
||||
IncrementTagFunctor() : mBy(1), mArgMoved(false) { }
|
||||
IncrementTagFunctor() : mBy(1) { }
|
||||
|
||||
void operator()(BasicValue& aValue)
|
||||
{
|
||||
aValue.SetTag(aValue.GetTag() + mBy.GetTag());
|
||||
}
|
||||
|
||||
void operator()(BasicValue& aValue, const BasicValue& aArg)
|
||||
{
|
||||
mArgMoved = false;
|
||||
aValue.SetTag(aValue.GetTag() + aArg.GetTag());
|
||||
}
|
||||
|
||||
void operator()(BasicValue& aValue, BasicValue&& aArg)
|
||||
{
|
||||
mArgMoved = true;
|
||||
aValue.SetTag(aValue.GetTag() + aArg.GetTag());
|
||||
}
|
||||
|
||||
BasicValue mBy;
|
||||
bool mArgMoved;
|
||||
};
|
||||
|
||||
static bool
|
||||
@ -578,8 +552,6 @@ TestApply()
|
||||
Maybe<BasicValue> mayValue;
|
||||
mayValue.apply(&IncrementTag);
|
||||
mayValue.apply(&AccessValue);
|
||||
mayValue.apply(&IncrementTagBy, 1);
|
||||
mayValue.apply(&AccessValueWithArg, 1);
|
||||
MOZ_RELEASE_ASSERT(!gFunctionWasApplied);
|
||||
|
||||
// Check that apply handles the 'Some' case.
|
||||
@ -590,22 +562,12 @@ TestApply()
|
||||
gFunctionWasApplied = false;
|
||||
mayValue.apply(&AccessValue);
|
||||
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
||||
gFunctionWasApplied = false;
|
||||
mayValue.apply(&IncrementTagBy, 2);
|
||||
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
||||
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 4);
|
||||
gFunctionWasApplied = false;
|
||||
mayValue.apply(&AccessValueWithArg, 1);
|
||||
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
||||
|
||||
// Check that apply works with a const reference.
|
||||
const Maybe<BasicValue>& mayValueCRef = mayValue;
|
||||
gFunctionWasApplied = false;
|
||||
mayValueCRef.apply(&AccessValue);
|
||||
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
||||
gFunctionWasApplied = false;
|
||||
mayValueCRef.apply(&AccessValueWithArg, 1);
|
||||
MOZ_RELEASE_ASSERT(gFunctionWasApplied);
|
||||
|
||||
// Check that apply works with functors.
|
||||
IncrementTagFunctor tagIncrementer;
|
||||
@ -614,15 +576,17 @@ TestApply()
|
||||
mayValue.apply(tagIncrementer);
|
||||
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 2);
|
||||
MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed);
|
||||
mayValue.apply(tagIncrementer, BasicValue(2));
|
||||
|
||||
// Check that apply works with lambda expressions.
|
||||
int32_t two = 2;
|
||||
gFunctionWasApplied = false;
|
||||
mayValue = Some(BasicValue(2));
|
||||
mayValue.apply([&](BasicValue& aVal) { aVal.SetTag(aVal.GetTag() * two); });
|
||||
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 4);
|
||||
MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed);
|
||||
MOZ_RELEASE_ASSERT(tagIncrementer.mArgMoved == true);
|
||||
BasicValue incrementBy(3);
|
||||
mayValue.apply(tagIncrementer, incrementBy);
|
||||
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 7);
|
||||
MOZ_RELEASE_ASSERT(tagIncrementer.mBy.GetStatus() == eWasConstructed);
|
||||
MOZ_RELEASE_ASSERT(tagIncrementer.mArgMoved == false);
|
||||
mayValue.apply([=](BasicValue& aVal) { aVal.SetTag(aVal.GetTag() * two); });
|
||||
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 8);
|
||||
mayValueCRef.apply([&](const BasicValue& aVal) { gFunctionWasApplied = true; });
|
||||
MOZ_RELEASE_ASSERT(gFunctionWasApplied == true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -641,43 +605,16 @@ TimesTwoAndResetOriginal(BasicValue& aValue)
|
||||
return tag * 2;
|
||||
}
|
||||
|
||||
static int
|
||||
TimesNum(const BasicValue& aValue, int aNum)
|
||||
{
|
||||
return aValue.GetTag() * aNum;
|
||||
}
|
||||
|
||||
static int
|
||||
TimesNumAndResetOriginal(BasicValue& aValue, int aNum)
|
||||
{
|
||||
int tag = aValue.GetTag();
|
||||
aValue.SetTag(1);
|
||||
return tag * aNum;
|
||||
}
|
||||
|
||||
struct MultiplyTagFunctor
|
||||
{
|
||||
MultiplyTagFunctor() : mBy(2), mArgMoved(false) { }
|
||||
MultiplyTagFunctor() : mBy(2) { }
|
||||
|
||||
int operator()(BasicValue& aValue)
|
||||
{
|
||||
return aValue.GetTag() * mBy.GetTag();
|
||||
}
|
||||
|
||||
int operator()(BasicValue& aValue, const BasicValue& aArg)
|
||||
{
|
||||
mArgMoved = false;
|
||||
return aValue.GetTag() * aArg.GetTag();
|
||||
}
|
||||
|
||||
int operator()(BasicValue& aValue, BasicValue&& aArg)
|
||||
{
|
||||
mArgMoved = true;
|
||||
return aValue.GetTag() * aArg.GetTag();
|
||||
}
|
||||
|
||||
BasicValue mBy;
|
||||
bool mArgMoved;
|
||||
};
|
||||
|
||||
static bool
|
||||
@ -690,11 +627,6 @@ TestMap()
|
||||
DECLTYPE(mayValue.map(&TimesTwo))>::value,
|
||||
"map(TimesTwo) should return a Maybe<int>");
|
||||
MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwoAndResetOriginal) == Nothing());
|
||||
MOZ_RELEASE_ASSERT(mayValue.map(&TimesNum, 3) == Nothing());
|
||||
static_assert(IsSame<Maybe<int>,
|
||||
DECLTYPE(mayValue.map(&TimesNum, 3))>::value,
|
||||
"map(TimesNum, 3) should return a Maybe<int>");
|
||||
MOZ_RELEASE_ASSERT(mayValue.map(&TimesNumAndResetOriginal, 3) == Nothing());
|
||||
|
||||
// Check that map handles the 'Some' case.
|
||||
mayValue = Some(BasicValue(2));
|
||||
@ -702,9 +634,6 @@ TestMap()
|
||||
MOZ_RELEASE_ASSERT(mayValue.map(&TimesTwoAndResetOriginal) == Some(4));
|
||||
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 1);
|
||||
mayValue = Some(BasicValue(2));
|
||||
MOZ_RELEASE_ASSERT(mayValue.map(&TimesNum, 3) == Some(6));
|
||||
MOZ_RELEASE_ASSERT(mayValue.map(&TimesNumAndResetOriginal, 3) == Some(6));
|
||||
MOZ_RELEASE_ASSERT(mayValue->GetTag() == 1);
|
||||
|
||||
// Check that map works with a const reference.
|
||||
mayValue->SetTag(2);
|
||||
@ -713,27 +642,31 @@ TestMap()
|
||||
static_assert(IsSame<Maybe<int>,
|
||||
DECLTYPE(mayValueCRef.map(&TimesTwo))>::value,
|
||||
"map(TimesTwo) should return a Maybe<int>");
|
||||
MOZ_RELEASE_ASSERT(mayValueCRef.map(&TimesNum, 3) == Some(6));
|
||||
static_assert(IsSame<Maybe<int>,
|
||||
DECLTYPE(mayValueCRef.map(&TimesNum, 3))>::value,
|
||||
"map(TimesNum, 3) should return a Maybe<int>");
|
||||
|
||||
// Check that map works with functors.
|
||||
// XXX(seth): Support for functors will be added in bug 1054115; it had to be
|
||||
// ripped out temporarily because of incompatibilities with GCC 4.4.
|
||||
/*
|
||||
MultiplyTagFunctor tagMultiplier;
|
||||
MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed);
|
||||
MOZ_RELEASE_ASSERT(mayValue.map(tagMultiplier) == Some(4));
|
||||
MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed);
|
||||
MOZ_RELEASE_ASSERT(mayValue.map(tagMultiplier, BasicValue(3)) == Some(6));
|
||||
MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed);
|
||||
MOZ_RELEASE_ASSERT(tagMultiplier.mArgMoved == true);
|
||||
BasicValue multiplyBy(3);
|
||||
MOZ_RELEASE_ASSERT(mayValue.map(tagMultiplier, multiplyBy) == Some(6));
|
||||
MOZ_RELEASE_ASSERT(tagMultiplier.mBy.GetStatus() == eWasConstructed);
|
||||
MOZ_RELEASE_ASSERT(tagMultiplier.mArgMoved == false);
|
||||
*/
|
||||
|
||||
// Check that map works with lambda expressions.
|
||||
int two = 2;
|
||||
mayValue = Some(BasicValue(2));
|
||||
Maybe<int> mappedValue =
|
||||
mayValue.map([&](const BasicValue& aVal) {
|
||||
return aVal.GetTag() * two;
|
||||
});
|
||||
MOZ_RELEASE_ASSERT(mappedValue == Some(4));
|
||||
mappedValue =
|
||||
mayValue.map([=](const BasicValue& aVal) {
|
||||
return aVal.GetTag() * two;
|
||||
});
|
||||
MOZ_RELEASE_ASSERT(mappedValue == Some(4));
|
||||
mappedValue =
|
||||
mayValueCRef.map([&](const BasicValue& aVal) {
|
||||
return aVal.GetTag() * two;
|
||||
});
|
||||
MOZ_RELEASE_ASSERT(mappedValue == Some(4));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user