зеркало из https://github.com/mozilla/moz-skia.git
Make the clip reducer operate on int rects. Remove redundant Gr from func
name. R=robertphillips@google.com Review URL: https://codereview.appspot.com/6890045 git-svn-id: http://skia.googlecode.com/svn/trunk@6688 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
0264fb4543
Коммит
34cd70a581
|
@ -13,6 +13,13 @@ typedef SkClipStack::Element Element;
|
|||
|
||||
namespace GrReducedClip {
|
||||
|
||||
// helper function
|
||||
void reduced_stack_walker(const SkClipStack& stack,
|
||||
const SkRect& queryBounds,
|
||||
ElementList* result,
|
||||
InitialState* initialState,
|
||||
bool* requiresAA);
|
||||
|
||||
/*
|
||||
There are plenty of optimizations that could be added here. For example we could consider
|
||||
checking for cases where an inverse path can be changed to a regular fill with a different op.
|
||||
|
@ -22,10 +29,12 @@ for the case where the bounds are kInsideOut_BoundsType. We could restrict earli
|
|||
based on later intersect operations, and perhaps remove intersect-rects. We could optionally
|
||||
take a rect in case the caller knows a bound on what is to be drawn through this clip.
|
||||
*/
|
||||
void GrReduceClipStack(const SkClipStack& stack,
|
||||
const SkRect& queryBounds,
|
||||
ElementList* result,
|
||||
InitialState* initialState) {
|
||||
void ReduceClipStack(const SkClipStack& stack,
|
||||
const SkIRect& queryBounds,
|
||||
ElementList* result,
|
||||
InitialState* initialState,
|
||||
SkIRect* tighterBounds,
|
||||
bool* requiresAA) {
|
||||
result->reset();
|
||||
|
||||
if (stack.isWideOpen()) {
|
||||
|
@ -33,39 +42,98 @@ void GrReduceClipStack(const SkClipStack& stack,
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
// We initially look at whether the bounds alone is sufficient. We also use the stack bounds to
|
||||
// attempt to compute the tighterBounds.
|
||||
|
||||
SkClipStack::BoundsType stackBoundsType;
|
||||
SkRect stackBounds;
|
||||
bool iior;
|
||||
stack.getBounds(&stackBounds, &stackBoundsType, &iior);
|
||||
|
||||
const SkIRect* bounds = &queryBounds;
|
||||
|
||||
SkRect scalarQueryBounds = SkRect::MakeFromIRect(queryBounds);
|
||||
|
||||
if (iior) {
|
||||
SkASSERT(SkClipStack::kNormal_BoundsType == stackBoundsType);
|
||||
SkRect isectRect;
|
||||
if (stackBounds.contains(queryBounds)) {
|
||||
if (stackBounds.contains(scalarQueryBounds)) {
|
||||
*initialState = kAllIn_InitialState;
|
||||
} else if (isectRect.intersect(stackBounds, queryBounds)) {
|
||||
// iior should only be true if aa/non-aa status matches among all elements.
|
||||
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
|
||||
bool doAA = iter.prev()->isAA();
|
||||
SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion::kReplace_Op, doAA));
|
||||
if (NULL != tighterBounds) {
|
||||
*tighterBounds = queryBounds;
|
||||
}
|
||||
if (NULL != requiresAA) {
|
||||
*requiresAA = false;
|
||||
}
|
||||
} else if (isectRect.intersect(stackBounds, scalarQueryBounds)) {
|
||||
if (NULL != tighterBounds) {
|
||||
isectRect.roundOut(tighterBounds);
|
||||
SkRect scalarTighterBounds = SkRect::MakeFromIRect(*tighterBounds);
|
||||
if (scalarTighterBounds == isectRect) {
|
||||
// the round-out didn't add any area outside the clip rect.
|
||||
*requiresAA = false;
|
||||
*initialState = kAllIn_InitialState;
|
||||
return;
|
||||
}
|
||||
*initialState = kAllOut_InitialState;
|
||||
// iior should only be true if aa/non-aa status matches among all elements.
|
||||
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
|
||||
bool doAA = iter.prev()->isAA();
|
||||
SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion::kReplace_Op, doAA));
|
||||
if (NULL != requiresAA) {
|
||||
*requiresAA = doAA;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*initialState = kAllOut_InitialState;
|
||||
if (NULL != requiresAA) {
|
||||
*requiresAA = false;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (SkClipStack::kNormal_BoundsType == stackBoundsType) {
|
||||
if (!SkRect::Intersects(stackBounds, queryBounds)) {
|
||||
if (!SkRect::Intersects(stackBounds, scalarQueryBounds)) {
|
||||
*initialState = kAllOut_InitialState;
|
||||
if (NULL != requiresAA) {
|
||||
*requiresAA = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (NULL != tighterBounds) {
|
||||
SkIRect stackIBounds;
|
||||
stackBounds.roundOut(&stackIBounds);
|
||||
tighterBounds->intersect(queryBounds, stackIBounds);
|
||||
bounds = tighterBounds;
|
||||
}
|
||||
} else {
|
||||
if (stackBounds.contains(queryBounds)) {
|
||||
if (stackBounds.contains(scalarQueryBounds)) {
|
||||
*initialState = kAllOut_InitialState;
|
||||
if (NULL != requiresAA) {
|
||||
*requiresAA = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (NULL != tighterBounds) {
|
||||
*tighterBounds = queryBounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SkRect scalarBounds = SkRect::MakeFromIRect(*bounds);
|
||||
|
||||
// Now that we have determined the bounds to use and filtered out the trivial cases, call the
|
||||
// helper that actually walks the stack.
|
||||
reduced_stack_walker(stack, scalarBounds, result, initialState, requiresAA);
|
||||
}
|
||||
|
||||
void reduced_stack_walker(const SkClipStack& stack,
|
||||
const SkRect& queryBounds,
|
||||
ElementList* result,
|
||||
InitialState* initialState,
|
||||
bool* requiresAA) {
|
||||
|
||||
// walk backwards until we get to:
|
||||
// a) the beginning
|
||||
// b) an operation that is known to make the bounds all inside/outside
|
||||
|
@ -80,6 +148,7 @@ void GrReduceClipStack(const SkClipStack& stack,
|
|||
bool emsmallens = false;
|
||||
|
||||
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
|
||||
int numAAElements = 0;
|
||||
while ((kUnknown_InitialState == *initialState)) {
|
||||
const Element* element = iter.prev();
|
||||
if (NULL == element) {
|
||||
|
@ -254,6 +323,9 @@ void GrReduceClipStack(const SkClipStack& stack,
|
|||
(queryBounds, SkRegion::kReverseDifference_Op, false));
|
||||
} else {
|
||||
result->addToHead(*element);
|
||||
if (element->isAA()) {
|
||||
++numAAElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +334,6 @@ void GrReduceClipStack(const SkClipStack& stack,
|
|||
(kAllIn_InitialState == *initialState && !emsmallens)) {
|
||||
result->reset();
|
||||
} else {
|
||||
int clipsToSkip = 0;
|
||||
Element* element = result->headIter().get();
|
||||
while (NULL != element) {
|
||||
bool skippable = false;
|
||||
|
@ -308,7 +379,6 @@ void GrReduceClipStack(const SkClipStack& stack,
|
|||
}
|
||||
break;
|
||||
case SkRegion::kReplace_Op:
|
||||
SkASSERT(!clipsToSkip); // replace should always be the first op
|
||||
skippable = false; // we would have skipped it in the backwards walk if we
|
||||
// could've.
|
||||
break;
|
||||
|
@ -319,10 +389,16 @@ void GrReduceClipStack(const SkClipStack& stack,
|
|||
if (!skippable) {
|
||||
break;
|
||||
} else {
|
||||
if (element->isAA()) {
|
||||
--numAAElements;
|
||||
}
|
||||
result->popHead();
|
||||
element = result->headIter().get();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NULL != requiresAA) {
|
||||
*requiresAA = numAAElements > 0;
|
||||
}
|
||||
}
|
||||
} // namespace GrReducedClip
|
||||
|
|
|
@ -22,12 +22,19 @@ enum InitialState {
|
|||
* This function takes a clip stack and a query rectangle and it produces a reduced set of
|
||||
* SkClipStack::Elements that are equivalent to applying the full stack to the rectangle. The
|
||||
* initial state of the query rectangle before the first clip element is applied is returned via
|
||||
* initialState. This function is declared here so that it can be unit-tested. It may become a
|
||||
* member function of SkClipStack when its interface is determined to be stable.
|
||||
* initialState. Optionally, the caller can request a tighter bounds on the clip be returned via
|
||||
* tighterBounds. If not NULL, tighterBounds will always be contained by queryBounds after return.
|
||||
* If tighterBounds is specified then it is assumed that the caller will implicitly clip against it.
|
||||
* If the caller specifies non-NULL for requiresAA then it will indicate whether anti-aliasing is
|
||||
* required to process any of the elements in the result.
|
||||
*
|
||||
* This may become a member function of SkClipStack when its interface is determined to be stable.
|
||||
*/
|
||||
void GrReduceClipStack(const SkClipStack& stack,
|
||||
const SkRect& queryBounds,
|
||||
ElementList* result,
|
||||
InitialState* initialState);
|
||||
void ReduceClipStack(const SkClipStack& stack,
|
||||
const SkIRect& queryBounds,
|
||||
ElementList* result,
|
||||
InitialState* initialState,
|
||||
SkIRect* tighterBounds = NULL,
|
||||
bool* requiresAA = NULL);
|
||||
|
||||
} // namespace GrReducedClip
|
||||
|
|
|
@ -669,7 +669,13 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter) {
|
|||
ElementList reducedClips;
|
||||
|
||||
GrReducedClip::InitialState initial;
|
||||
GrReducedClip::GrReduceClipStack(stack, inflatedBounds, &reducedClips, &initial);
|
||||
SkIRect tBounds;
|
||||
SkIRect* tightBounds = r.nextBool() ? &tBounds : NULL;
|
||||
GrReducedClip::ReduceClipStack(stack,
|
||||
inflatedIBounds,
|
||||
&reducedClips,
|
||||
&initial,
|
||||
tightBounds);
|
||||
|
||||
// Build a new clip stack based on the reduced clip elements
|
||||
SkClipStack reducedStack;
|
||||
|
@ -681,6 +687,11 @@ static void test_reduced_clip_stack(skiatest::Reporter* reporter) {
|
|||
add_elem_to_stack(*iter.get(), &reducedStack);
|
||||
}
|
||||
|
||||
// GrReducedClipStack assumes that the final result is clipped to the returned bounds
|
||||
if (NULL != tightBounds) {
|
||||
reducedStack.clipDevRect(*tightBounds, SkRegion::kIntersect_Op);
|
||||
}
|
||||
|
||||
// convert both the original stack and reduced stack to SkRegions and see if they're equal
|
||||
SkRegion region;
|
||||
SkRegion reducedRegion;
|
||||
|
|
Загрузка…
Ссылка в новой задаче