rename setXfermode(Mode) to setXfermodeMode(...) for clarity
fix memory leak in said method
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index a721479..5a01cd6 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -460,7 +460,7 @@
         paint, returning the mode that was set. If the Mode is SrcOver, then
         the paint's xfermode is set to null.
      */
-    SkXfermode* setXfermode(SkXfermode::Mode);
+    SkXfermode* setXfermodeMode(SkXfermode::Mode);
 
     /** Get the paint's patheffect object.
         <p />
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 28772b0..2413168 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1234,7 +1234,7 @@
 
     paint.setARGB(a, r, g, b);
     if (SkXfermode::kSrcOver_Mode != mode) {
-        paint.setXfermode(mode);
+        paint.setXfermodeMode(mode);
     }
     this->drawPaint(paint);
 }
@@ -1244,7 +1244,7 @@
 
     paint.setColor(c);
     if (SkXfermode::kSrcOver_Mode != mode) {
-        paint.setXfermode(mode);
+        paint.setXfermodeMode(mode);
     }
     this->drawPaint(paint);
 }
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 8146ff8..fa3eb55 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -873,15 +873,33 @@
     }
 }
 
-static inline bool just_translate(const SkMatrix& m) {
-    return (m.getType() & ~SkMatrix::kTranslate_Mask) == 0;
+/** For the purposes of drawing bitmaps, if a matrix is "almost" translate
+    go ahead and treat it as if it were, so that subsequent code can go fast.
+ */
+static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
+    SkMatrix::TypeMask mask = matrix.getType();
+
+    if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
+        return false;
+    }
+    if (mask & SkMatrix::kScale_Mask) {
+        SkScalar sx = matrix[SkMatrix::kMScaleX];
+        SkScalar sy = matrix[SkMatrix::kMScaleY];
+        int w = bitmap.width();
+        int h = bitmap.height();
+        int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w)));
+        int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h)));
+        return sw == w && sh == h;
+    }
+    // if we got here, we're either kTranslate_Mask or identity
+    return true;
 }
 
 void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
                               const SkPaint& paint) const {
     SkASSERT(bitmap.getConfig() == SkBitmap::kA8_Config);
 
-    if (just_translate(*fMatrix)) {        
+    if (just_translate(*fMatrix, bitmap)) {        
         int ix = SkScalarRound(fMatrix->getTranslateX());
         int iy = SkScalarRound(fMatrix->getTranslateY());
 
@@ -1005,7 +1023,8 @@
         return;
     }
 
-    if (bitmap.getConfig() != SkBitmap::kA8_Config && just_translate(matrix)) {
+    if (bitmap.getConfig() != SkBitmap::kA8_Config &&
+            just_translate(matrix, bitmap)) {
         int         ix = SkScalarRound(matrix.getTranslateX());
         int         iy = SkScalarRound(matrix.getTranslateY());
         uint32_t    storage[kBlitterStorageLongCount];
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 2320b1f..8b2a21b 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1437,6 +1437,12 @@
     return mode;
 }
 
+SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
+    SkSafeUnref(fXfermode);
+    fXfermode = SkXfermode::Create(mode);
+    return fXfermode;
+}
+
 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect)
 {
     SkRefCnt_SafeAssign(fPathEffect, effect);
@@ -1449,11 +1455,6 @@
     return filter;
 }
 
-// Helpers
-SkXfermode* SkPaint::setXfermode(SkXfermode::Mode mode) {
-    return this->setXfermode(SkXfermode::Create(mode));
-}
-
 ////////////////////////////////////////////////////////////////////////////////////////
 
 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const