Fixed lingering gpu-path AA clip mask generation bug

http://codereview.appspot.com/6351055/



git-svn-id: http://skia.googlecode.com/svn/trunk@4416 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index f67336f..e34151c 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -52,17 +52,17 @@
 /**
  * Draw a single rect element of the clip stack into the accumulation bitmap
  */
-void GrSWMaskHelper::draw(const GrRect& clientRect, SkRegion::Op op, 
-                          bool antiAlias, GrColor color) {
+void GrSWMaskHelper::draw(const GrRect& rect, SkRegion::Op op, 
+                          bool antiAlias, uint8_t alpha) {
     SkPaint paint;
 
     SkXfermode* mode = SkXfermode::Create(op_to_mode(op));
 
     paint.setXfermode(mode);
     paint.setAntiAlias(antiAlias);
-    paint.setColor(color);
+    paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
 
-    fDraw.drawRect(clientRect, paint);
+    fDraw.drawRect(rect, paint);
 
     SkSafeUnref(mode);
 }
@@ -70,12 +70,12 @@
 /**
  * Draw a single path element of the clip stack into the accumulation bitmap
  */
-void GrSWMaskHelper::draw(const SkPath& clientPath, SkRegion::Op op,
-                          GrPathFill fill, bool antiAlias, GrColor color) {
+void GrSWMaskHelper::draw(const SkPath& path, SkRegion::Op op,
+                          GrPathFill fill, bool antiAlias, uint8_t alpha) {
 
     SkPaint paint;
     SkPath tmpPath;
-    const SkPath* pathToDraw = &clientPath;
+    const SkPath* pathToDraw = &path;
     if (kHairLine_GrPathFill == fill) {
         paint.setStyle(SkPaint::kStroke_Style);
         paint.setStrokeWidth(SK_Scalar1);
@@ -92,30 +92,26 @@
 
     paint.setXfermode(mode);
     paint.setAntiAlias(antiAlias);
-    paint.setColor(color);
+    paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
 
     fDraw.drawPath(*pathToDraw, paint);
 
     SkSafeUnref(mode);
 }
 
-bool GrSWMaskHelper::init(const GrIRect& pathDevBounds, 
-                          const GrPoint* translate,
-                          bool useMatrix) {
-    if (useMatrix) {    
-        fMatrix = fContext->getMatrix();
+bool GrSWMaskHelper::init(const GrIRect& resultBounds, 
+                          const GrMatrix* matrix) {
+    if (NULL != matrix) {
+        fMatrix = *matrix;
     } else {
         fMatrix.setIdentity();
     }
 
-    if (NULL != translate) {
-        fMatrix.postTranslate(translate->fX, translate->fY);
-    }
-
-    fMatrix.postTranslate(-pathDevBounds.fLeft * SK_Scalar1,
-                          -pathDevBounds.fTop * SK_Scalar1);
-    GrIRect bounds = GrIRect::MakeWH(pathDevBounds.width(),
-                                     pathDevBounds.height());
+    // Now translate so the bound's UL corner is at the origin
+    fMatrix.postTranslate(-resultBounds.fLeft * SK_Scalar1,
+                          -resultBounds.fTop * SK_Scalar1);
+    GrIRect bounds = GrIRect::MakeWH(resultBounds.width(),
+                                     resultBounds.height());
 
     fBM.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
     if (!fBM.allocPixels()) {
@@ -133,28 +129,23 @@
 }
 
 /**
- * Get a texture (from the texture cache) of the correct size & format
+ * Get a texture (from the texture cache) of the correct size & format.
+ * Return true on success; false on failure.
  */
-bool GrSWMaskHelper::getTexture(GrAutoScratchTexture* tex) {
+bool GrSWMaskHelper::getTexture(GrAutoScratchTexture* texture) {
     GrTextureDesc desc;
     desc.fWidth = fBM.width();
     desc.fHeight = fBM.height();
     desc.fConfig = kAlpha_8_GrPixelConfig;
 
-    tex->set(fContext, desc);
-    GrTexture* texture = tex->texture();
-
-    if (NULL == texture) {
-        return false;
-    }
-
-    return true;
+    texture->set(fContext, desc);
+    return NULL != texture->texture();
 }
 
 /**
  * Move the result of the software mask generation back to the gpu
  */
-void GrSWMaskHelper::toTexture(GrTexture *texture, bool clearToWhite) {
+void GrSWMaskHelper::toTexture(GrTexture *texture, uint8_t alpha) {
     SkAutoLockPixels alp(fBM);
 
     // The destination texture is almost always larger than "fBM". Clear
@@ -163,19 +154,45 @@
     
     // "texture" needs to be installed as the render target for the clear
     // and the texture upload but cannot remain the render target upon
-    // returned. Callers typically use it as a texture and it would then
+    // return. Callers typically use it as a texture and it would then
     // be both source and dest.
     GrDrawState::AutoRenderTargetRestore artr(fContext->getGpu()->drawState(), 
                                               texture->asRenderTarget());
 
-    if (clearToWhite) {
-        fContext->getGpu()->clear(NULL, SK_ColorWHITE);
-    } else {
-        fContext->getGpu()->clear(NULL, 0x00000000);
-    }
+    fContext->getGpu()->clear(NULL, SkColorSetARGB(alpha, alpha, alpha, alpha));
 
     texture->writePixels(0, 0, fBM.width(), fBM.height(), 
                          kAlpha_8_GrPixelConfig,
                          fBM.getPixels(), fBM.rowBytes());
 }
 
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Software rasterizes path to A8 mask (possibly using the context's matrix) 
+ * and uploads the result to a scratch texture. Returns true on success; 
+ * false on failure.
+ */
+bool GrSWMaskHelper::DrawToTexture(GrContext* context,
+                                   const SkPath& path,
+                                   const GrIRect& resultBounds,
+                                   GrPathFill fill,
+                                   GrAutoScratchTexture* result,
+                                   bool antiAlias,
+                                   GrMatrix* matrix) {
+    GrSWMaskHelper helper(context);
+
+    if (!helper.init(resultBounds, matrix)) {
+        return false;
+    }
+
+    helper.draw(path, SkRegion::kReplace_Op, fill, antiAlias, 0xFF);
+
+    if (!helper.getTexture(result)) {
+        return false;
+    }
+
+    helper.toTexture(result->texture(), 0x00);
+
+    return true;
+}
+