/** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
making the rectangle narrower. If dx is negative, then the sides are moved outwards,
- making the rectangle wider. The same hods true for dy and the top and bottom.
+ making the rectangle wider. The same holds true for dy and the top and bottom.
*/
void inset(int32_t dx, int32_t dy) {
fLeft += dx;
fBottom -= dy;
}
+ /** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
+ moved outwards, making the rectangle wider. If dx is negative, then the
+ sides are moved inwards, making the rectangle narrower. The same holds
+ true for dy and the top and bottom.
+ */
+ void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
+
bool quickReject(int l, int t, int r, int b) const {
return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
}
/** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
moved outwards, making the rectangle wider. If dx is negative, then the
- sides are moved inwards, making the rectangle narrower. The same hods
+ sides are moved inwards, making the rectangle narrower. The same holds
true for dy and the top and bottom.
*/
void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }
// sampler matrix this also alters the vertex layout
void setup_drawstate_aaclip(GrGpu* gpu,
GrTexture* result,
- const GrRect &bound) {
+ const GrIRect &bound) {
GrDrawState* drawState = gpu->drawState();
GrAssert(drawState);
GrMatrix mat;
mat.setIDiv(result->width(), result->height());
- mat.preTranslate(-bound.fLeft, -bound.fTop);
+ mat.preTranslate(SkIntToScalar(-bound.fLeft), SkIntToScalar(-bound.fTop));
mat.preConcat(drawState->getViewMatrix());
drawState->sampler(maskStage)->reset(GrSamplerState::kClamp_WrapMode,
// The clip geometry is complex enough that it will be more
// efficient to create it entirely in software
GrTexture* result = NULL;
- GrRect bound;
+ GrIRect bound;
if (this->createSoftwareClipMask(gpu, clipIn, &result, &bound)) {
fClipMaskInAlpha = true;
// render target) we aren't going to use scissoring like the stencil
// path does (see scissorSettings below)
GrTexture* result = NULL;
- GrRect bound;
+ GrIRect bound;
if (this->createAlphaClipMask(gpu, clipIn, &result, &bound)) {
fClipMaskInAlpha = true;
#endif
namespace {
+/**
+ * Does "container" contain "containee"? If either is empty then
+ * no containment is possible.
+ */
+bool contains(const SkRect& container, const SkIRect& containee) {
+ return !containee.isEmpty() && !container.isEmpty() &&
+ container.fLeft <= SkIntToScalar(containee.fLeft) &&
+ container.fTop <= SkIntToScalar(containee.fTop) &&
+ container.fRight >= SkIntToScalar(containee.fRight) &&
+ container.fBottom >= SkIntToScalar(containee.fBottom);
+}
+
+
////////////////////////////////////////////////////////////////////////////////
// determines how many elements at the head of the clip can be skipped and
// whether the initial clear should be to the inside- or outside-the-clip value,
// and what op should be used to draw the first element that isn't skipped.
int process_initial_clip_elements(const GrClip& clip,
- const GrRect& bounds,
+ const GrIRect& bounds,
bool* clearToInside,
SkRegion::Op* startOp) {
// if this element contains the entire bounds then we
// can skip it.
if (kRect_ClipType == clip.getElementType(curr)
- && clip.getRect(curr).contains(bounds)) {
+ && contains(clip.getRect(curr), bounds)) {
break;
}
// if everything is initially clearToInside then intersect is
// get a texture to act as a temporary buffer for AA clip boolean operations
// TODO: given the expense of createTexture we may want to just cache this too
-void GrClipMaskManager::getTemp(const GrRect& bounds,
+void GrClipMaskManager::getTemp(const GrIRect& bounds,
GrAutoScratchTexture* temp) {
if (NULL != temp->texture()) {
// we've already allocated the temp texture
const GrTextureDesc desc = {
kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit,
- SkScalarCeilToInt(bounds.width()),
- SkScalarCeilToInt(bounds.height()),
+ bounds.width(),
+ bounds.height(),
kAlpha_8_GrPixelConfig,
0 // samples
};
void GrClipMaskManager::setupCache(const GrClip& clipIn,
- const GrRect& bounds) {
+ const GrIRect& bounds) {
// Since we are setting up the cache we know the last lookup was a miss
// Free up the currently cached mask so it can be reused
fAACache.reset();
const GrTextureDesc desc = {
kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit,
- SkScalarCeilToInt(bounds.width()),
- SkScalarCeilToInt(bounds.height()),
+ bounds.width(),
+ bounds.height(),
kAlpha_8_GrPixelConfig,
0 // samples
};
bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
- GrRect *resultBounds) {
+ GrIRect *resultBounds) {
GrDrawState* origDrawState = gpu->drawState();
GrAssert(origDrawState->isClipState());
bounds = rtRect;
}
- bounds.roundOut();
+ GrIRect intBounds;
+ bounds.roundOut(&intBounds);
// need to outset a pixel since the standard bounding box computation
// path doesn't leave any room for antialiasing (esp. w.r.t. rects)
- bounds.outset(SkIntToScalar(1), SkIntToScalar(1));
+ intBounds.outset(1, 1);
// TODO: make sure we don't outset if bounds are still 0,0 @ min
- GrAssert(SkScalarIsInt(bounds.width()));
- GrAssert(SkScalarIsInt(bounds.height()));
-
if (fAACache.canReuse(clipIn,
- SkScalarCeilToInt(bounds.width()),
- SkScalarCeilToInt(bounds.height()))) {
+ intBounds.width(),
+ intBounds.height())) {
*result = fAACache.getLastMask();
fAACache.getLastBound(resultBounds);
return true;
}
- this->setupCache(clipIn, bounds);
+ this->setupCache(clipIn, intBounds);
- *resultBounds = bounds;
+ *resultBounds = intBounds;
return false;
}
bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
- GrRect *resultBounds) {
+ GrIRect *resultBounds) {
if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
return true;
// offset the paths & rects that will be used to compute it
GrMatrix m;
- m.setTranslate(-resultBounds->fLeft, -resultBounds->fTop);
+ m.setTranslate(SkIntToScalar(-resultBounds->fLeft),
+ SkIntToScalar(-resultBounds->fTop));
drawState->setViewMatrix(m);
}
// there is no point in intersecting a screen filling rectangle.
if (SkRegion::kIntersect_Op == op &&
kRect_ClipType == clipIn.getElementType(c) &&
- clipIn.getRect(c).contains(*resultBounds)) {
+ contains(clipIn.getRect(c), *resultBounds)) {
continue;
}
if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
GrMatrix m;
- m.setTranslate(resultBounds->fLeft, resultBounds->fTop);
+ m.setTranslate(SkIntToScalar(resultBounds->fLeft),
+ SkIntToScalar(resultBounds->fTop));
drawState->preConcatViewMatrix(m);
}
if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
GrMatrix m;
- m.setTranslate(-resultBounds->fLeft, -resultBounds->fTop);
+ m.setTranslate(SkIntToScalar(-resultBounds->fLeft),
+ SkIntToScalar(-resultBounds->fTop));
drawState->preConcatViewMatrix(m);
}
"Ganesh only handles 16b or smaller stencil buffers");
clipBit = (1 << (clipBit-1));
- GrRect rtRect;
- rtRect.setLTRB(0, 0,
- GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
+ GrIRect rtRect = GrIRect::MakeWH(rt->width(), rt->height());
bool clearToInside;
SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning
// there is no point in intersecting a screen filling
// rectangle.
if (SkRegion::kIntersect_Op == op &&
- clipCopy.getRect(c).contains(rtRect)) {
+ contains(clipCopy.getRect(c), rtRect)) {
continue;
}
} else {
bool GrClipMaskManager::createSoftwareClipMask(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
- GrRect *resultBounds) {
+ GrIRect *resultBounds) {
if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
return true;
void acquireMask(const GrClip& clip,
const GrTextureDesc& desc,
- const GrRect& bound) {
+ const GrIRect& bound) {
if (fStack.empty()) {
GrAssert(false);
return back->fLastMask.texture()->height();
}
- void getLastBound(GrRect* bound) const {
+ void getLastBound(GrIRect* bound) const {
if (fStack.empty()) {
GrAssert(false);
void acquireMask(GrContext* context,
const GrClip& clip,
const GrTextureDesc& desc,
- const GrRect& bound) {
+ const GrIRect& bound) {
fLastClip = clip;
// fLastBound stores the bounding box of the clip mask in canvas
// space. The left and top fields are used to offset the uvs for
// geometry drawn with this mask (in setupDrawStateAAClip)
- GrRect fLastBound;
+ GrIRect fLastBound;
};
GrContext* fContext;
bool createAlphaClipMask(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
- GrRect *resultBounds);
+ GrIRect *resultBounds);
bool createSoftwareClipMask(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
- GrRect *resultBounds);
+ GrIRect *resultBounds);
bool clipMaskPreamble(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
- GrRect *resultBounds);
+ GrIRect *resultBounds);
bool drawPath(GrGpu* gpu,
const SkPath& path,
GrTexture* target,
GrTexture* texture);
- void getTemp(const GrRect& bounds, GrAutoScratchTexture* temp);
+ void getTemp(const GrIRect& bounds, GrAutoScratchTexture* temp);
void setupCache(const GrClip& clip,
- const GrRect& bounds);
+ const GrIRect& bounds);
// determines the path renderer used to draw a clip path element.
GrPathRenderer* getClipPathRenderer(GrGpu* gpu,