Upstreaming changes from android.

- fix compile warnings in the GPU code
- upstream android specific code (ifdef protected)
- fail gracefully when a custom allocator fails



git-svn-id: http://skia.googlecode.com/svn/trunk@936 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrClip.h b/gpu/include/GrClip.h
index 00da110..54082b7 100644
--- a/gpu/include/GrClip.h
+++ b/gpu/include/GrClip.h
@@ -64,7 +64,7 @@
         return fList[i].fRect;
     }
 
-    const GrSetOp getOp(int i) const { return fList[i].fOp; }
+    GrSetOp getOp(int i) const { return fList[i].fOp; }
 
     bool isRect() const {
         if (1 == fList.count() && kRect_ClipType == fList[0].fType) {
diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index 285665b..aef5937 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -245,7 +245,7 @@
      * @param stage     the stage of sampler set
      * @param matrix    the matrix to set
      */
-    const void setSamplerMatrix(int stage, const GrMatrix& matrix) {
+    void setSamplerMatrix(int stage, const GrMatrix& matrix) {
         fCurrDrawState.fSamplerStates[stage].setMatrix(matrix);
     }
 
diff --git a/gpu/src/GrPathRenderer.h b/gpu/src/GrPathRenderer.h
index c2d30c0..19e284f 100644
--- a/gpu/src/GrPathRenderer.h
+++ b/gpu/src/GrPathRenderer.h
@@ -27,6 +27,8 @@
  */
 class GrPathRenderer {
 public:
+    virtual ~GrPathRenderer() { };
+
     /**
      * Draws a path into the draw target. The target will already have its draw
      * state configured for the draw.
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index 56d7478..1d21a2f 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -468,16 +468,29 @@
     */
     int extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy);
 
-    void extractAlpha(SkBitmap* dst) const {
-        this->extractAlpha(dst, NULL, NULL, NULL);
+    bool extractAlpha(SkBitmap* dst) const {
+        return this->extractAlpha(dst, NULL, NULL, NULL);
     }
 
-    void extractAlpha(SkBitmap* dst, const SkPaint* paint,
+    bool extractAlpha(SkBitmap* dst, const SkPaint* paint,
                       SkIPoint* offset) const {
-        this->extractAlpha(dst, paint, NULL, offset);
+        return this->extractAlpha(dst, paint, NULL, offset);
     }
 
-    void extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
+    /** Set dst to contain alpha layer of this bitmap. If destination bitmap
+        fails to be initialized, e.g. because allocator can't allocate pixels
+        for it, dst will not be modified and false will be returned.
+
+        @param dst The bitmap to be filled with alpha layer
+        @param paint The paint to draw with
+        @param allocator Allocator used to allocate the pixelref for the dst
+                         bitmap. If this is null, the standard HeapAllocator
+                         will be used.
+        @param offset If not null, it is set to top-left coordinate to position
+                      the returned bitmap so that it visually lines up with the
+                      original
+    */
+    bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
                       SkIPoint* offset) const;
 
     void flatten(SkFlattenableWriteBuffer&) const;
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index eef3aea..5aecacb 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -626,6 +626,21 @@
                                 const SkPath& path, const SkMatrix* matrix,
                                 const SkPaint& paint);
 
+#ifdef ANDROID
+    /** Draw the text on path, with each character/glyph origin specified by the pos[]
+        array. The origin is interpreted by the Align setting in the paint.
+        @param text The text to be drawn
+        @param byteLength   The number of bytes to read from the text parameter
+        @param pos      Array of positions, used to position each character
+        @param paint    The paint used for the text (e.g. color, size, style)
+        @param path The path to draw on
+        @param matrix The canvas matrix
+        */
+    void drawPosTextOnPath(const void* text, size_t byteLength,
+                           const SkPoint pos[], const SkPaint& paint,
+                           const SkPath& path, const SkMatrix* matrix);
+#endif
+
     /** Draw the picture into this canvas. This method effective brackets the
         playback of the picture's draw calls with save/restore, so the state
         of this canvas will be unchanged after this call. This contrasts with
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 48b86c2..55d823b 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -197,6 +197,11 @@
     virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
                                 const SkPath& path, const SkMatrix* matrix,
                                 const SkPaint& paint);
+#ifdef ANDROID
+    virtual void drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
+                                   const SkPoint pos[], const SkPaint& paint,
+                                   const SkPath& path, const SkMatrix* matrix);
+#endif
     virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
                               const SkPoint verts[], const SkPoint texs[],
                               const SkColor colors[], SkXfermode* xmode,
diff --git a/include/core/SkDraw.h b/include/core/SkDraw.h
index 1c4a621..99ab342 100644
--- a/include/core/SkDraw.h
+++ b/include/core/SkDraw.h
@@ -55,6 +55,11 @@
                         int scalarsPerPosition, const SkPaint& paint) const;
     void    drawTextOnPath(const char text[], size_t byteLength,
                         const SkPath&, const SkMatrix*, const SkPaint&) const;
+#ifdef ANDROID
+    void    drawPosTextOnPath(const char text[], size_t byteLength,
+                              const SkPoint pos[], const SkPaint& paint,
+                              const SkPath& path, const SkMatrix* matrix) const;
+#endif
     void    drawVertices(SkCanvas::VertexMode mode, int count,
                          const SkPoint vertices[], const SkPoint textures[],
                          const SkColor colors[], SkXfermode* xmode,
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h
index e669f2c..3c69251 100644
--- a/include/core/SkFontHost.h
+++ b/include/core/SkFontHost.h
@@ -278,6 +278,18 @@
 
     static void SetSubpixelOrder(LCDOrder order);
     static LCDOrder GetSubpixelOrder();
+
+#ifdef ANDROID
+    ///////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Return the number of font units per em.
+     *
+     * @param fontID the font to query.
+     * @return the number of font units per em or 0 on error.
+     */
+    static uint32_t GetUnitsPerEm(SkFontID fontID);
+#endif
 };
 
 #endif
diff --git a/include/core/SkRegion.h b/include/core/SkRegion.h
index 58f4f3f..7ddf087 100644
--- a/include/core/SkRegion.h
+++ b/include/core/SkRegion.h
@@ -249,6 +249,12 @@
     */
     bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
 
+#ifdef ANDROID
+    /** Returns a new char* containing the list of rectangles in this region
+     */
+    char* toString();
+#endif
+
     /** Returns the sequence of rectangles, sorted in Y and X, that make up
         this region.
     */
diff --git a/include/effects/SkPorterDuff.h b/include/effects/SkPorterDuff.h
index 6f4ac20..54f81ea 100644
--- a/include/effects/SkPorterDuff.h
+++ b/include/effects/SkPorterDuff.h
@@ -52,6 +52,9 @@
         kMultiply_Mode, //!< [Sa * Da, Sc * Dc]
         kScreen_Mode,   //!< [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
         kAdd_Mode,      //!< Saturate(S + D)
+#ifdef ANDROID
+        kOverlay_Mode,
+#endif
 
         kModeCount
     };
diff --git a/include/utils/SkCamera.h b/include/utils/SkCamera.h
index 8bbcabf..6d76018 100644
--- a/include/utils/SkCamera.h
+++ b/include/utils/SkCamera.h
@@ -157,6 +157,10 @@
     void rotateY(SkScalar deg);
     void rotateZ(SkScalar deg);
 
+#ifdef ANDROID
+    void setCameraLocation(SkScalar x, SkScalar y, SkScalar z);
+#endif
+
     void getMatrix(SkMatrix*) const;
     void applyToCanvas(SkCanvas*) const;
 
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index c1a9998..a5f7d57 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -1237,10 +1237,11 @@
 #include "SkMaskFilter.h"
 #include "SkMatrix.h"
 
-void SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
+bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
                             Allocator *allocator, SkIPoint* offset) const {
     SkDEBUGCODE(this->validate();)
 
+    SkBitmap    tmpBitmap;
     SkMatrix    identity;
     SkMask      srcM, dstM;
 
@@ -1260,14 +1261,20 @@
         dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
     } else {
     NO_FILTER_CASE:
-        dst->setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
+        tmpBitmap.setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
                        srcM.fRowBytes);
-        dst->allocPixels(allocator, NULL);
-        GetBitmapAlpha(*this, dst->getAddr8(0, 0), srcM.fRowBytes);
+        if (!tmpBitmap.allocPixels(allocator, NULL)) {
+            // Allocation of pixels for alpha bitmap failed.
+            SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
+                    tmpBitmap.width(), tmpBitmap.height());
+            return false;
+        }
+        GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
         if (offset) {
             offset->set(0, 0);
         }
-        return;
+        tmpBitmap.swap(*dst);
+        return true;
     }
 
     SkAutoMaskImage srcCleanup(&srcM, true);
@@ -1279,14 +1286,22 @@
 
     SkAutoMaskImage dstCleanup(&dstM, false);
 
-    dst->setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
+    tmpBitmap.setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
                    dstM.fBounds.height(), dstM.fRowBytes);
-    dst->allocPixels(allocator, NULL);
-    memcpy(dst->getPixels(), dstM.fImage, dstM.computeImageSize());
+    if (!tmpBitmap.allocPixels(allocator, NULL)) {
+        // Allocation of pixels for alpha bitmap failed.
+        SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
+                tmpBitmap.width(), tmpBitmap.height());
+        return false;
+    }
+    memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
     if (offset) {
         offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
     }
-    SkDEBUGCODE(dst->validate();)
+    SkDEBUGCODE(tmpBitmap.validate();)
+
+    tmpBitmap.swap(*dst);
+    return true;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index a8d218a..2b7d588 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1401,6 +1401,22 @@
     ITER_END
 }
 
+#ifdef ANDROID
+void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength,
+                                 const SkPoint pos[], const SkPaint& paint,
+                                 const SkPath& path, const SkMatrix* matrix) {
+
+    ITER_BEGIN(paint, SkDrawFilter::kText_Type)
+
+    while (iter.next()) {
+        iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos,
+                                        paint, path, matrix);
+    }
+
+    ITER_END
+}
+#endif
+
 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
                             const SkPoint verts[], const SkPoint texs[],
                             const SkColor colors[], SkXfermode* xmode,
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 5e6376e..619a371 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -153,6 +153,14 @@
     draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
 }
 
+#ifdef ANDROID
+void SkDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
+                                     const SkPoint pos[], const SkPaint& paint,
+                                     const SkPath& path, const SkMatrix* matrix) {
+    draw.drawPosTextOnPath((const char*)text, len, pos, paint, path, matrix);
+}
+#endif
+
 void SkDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
                                 int vertexCount,
                                 const SkPoint verts[], const SkPoint textures[],
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 8378e73..ce0fa9b 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -1940,6 +1940,70 @@
     }
 }
 
+#ifdef ANDROID
+void SkDraw::drawPosTextOnPath(const char text[], size_t byteLength,
+                               const SkPoint pos[], const SkPaint& paint,
+                               const SkPath& path, const SkMatrix* matrix) const {
+    // nothing to draw
+    if (text == NULL || byteLength == 0 || fClip->isEmpty() ||
+        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
+        return;
+    }
+
+    SkMatrix scaledMatrix;
+    SkPathMeasure meas(path, false);
+
+    SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(
+            SkPaint::kForward_TextBufferDirection, true);
+
+    // Copied (modified) from SkTextToPathIter constructor to setup paint
+    SkPaint tempPaint(paint);
+
+    tempPaint.setLinearText(true);
+    tempPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
+
+    if (tempPaint.getPathEffect() == NULL && !(tempPaint.getStrokeWidth() > 0
+            && tempPaint.getStyle() != SkPaint::kFill_Style)) {
+        tempPaint.setStyle(SkPaint::kFill_Style);
+        tempPaint.setPathEffect(NULL);
+    }
+    // End copied from SkTextToPathIter constructor
+
+    // detach cache
+    SkGlyphCache* cache = tempPaint.detachCache(NULL);
+
+    // Must set scale, even if 1
+    SkScalar scale = SK_Scalar1;
+    scaledMatrix.setScale(scale, scale);
+
+    // Loop over all glyph ids
+    for (const char* stop = text + byteLength; text < stop; pos++) {
+
+        const SkGlyph& glyph = glyphCacheProc(cache, &text);
+        SkPath tmp;
+
+        const SkPath* glyphPath = cache->findPath(glyph);
+        if (glyphPath == NULL) {
+            continue;
+        }
+
+        SkMatrix m(scaledMatrix);
+        m.postTranslate(pos->fX, 0);
+
+        if (matrix) {
+            m.postConcat(*matrix);
+        }
+
+        morphpath(&tmp, *glyphPath, meas, m);
+        this->drawPath(tmp, tempPaint);
+
+    }
+
+    // re-attach cache
+    SkGlyphCache::AttachCache(cache);
+}
+#endif
+
 ///////////////////////////////////////////////////////////////////////////////
 
 struct VertState {
diff --git a/src/core/SkRegion.cpp b/src/core/SkRegion.cpp
index cfe22fa..18dafb0 100644
--- a/src/core/SkRegion.cpp
+++ b/src/core/SkRegion.cpp
@@ -19,6 +19,10 @@
 #include "SkTemplates.h"
 #include "SkThread.h"
 
+#ifdef ANDROID
+#include <stdio.h>
+#endif
+
 SkDEBUGCODE(int32_t gRgnAllocCounter;)
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
@@ -190,6 +194,35 @@
 
 //////////////////////////////////////////////////////////////////////////////////////
 
+#ifdef ANDROID
+char* SkRegion::toString()
+{
+    Iterator iter(*this);
+    int count = 0;
+    while (!iter.done()) {
+        count++;
+        iter.next();
+    }
+    // 4 ints, up to 10 digits each plus sign, 3 commas, '(', ')', SkRegion() and '\0'
+    const int max = (count*((11*4)+5))+11+1;
+    char* result = (char*)malloc(max);
+    if (result == NULL) {
+        return NULL;
+    }
+    count = sprintf(result, "SkRegion(");
+    iter.reset(*this);
+    while (!iter.done()) {
+        const SkIRect& r = iter.rect();
+        count += sprintf(result+count, "(%d,%d,%d,%d)", r.fLeft, r.fTop, r.fRight, r.fBottom);
+        iter.next();
+    }
+    count += sprintf(result+count, ")");
+    return result;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////
+
 int SkRegion::count_runtype_values(int* itop, int* ibot) const
 {
     if (this == NULL)
diff --git a/src/effects/SkPorterDuff.cpp b/src/effects/SkPorterDuff.cpp
index 58447ad..980ce29 100644
--- a/src/effects/SkPorterDuff.cpp
+++ b/src/effects/SkPorterDuff.cpp
@@ -29,7 +29,10 @@
     MAKE_PAIR(Lighten),
     MAKE_PAIR(Multiply),
     MAKE_PAIR(Screen),
-    { SkPorterDuff::kAdd_Mode, SkXfermode::kPlus_Mode }
+    { SkPorterDuff::kAdd_Mode, SkXfermode::kPlus_Mode },
+#ifdef ANDROID
+    MAKE_PAIR(Overlay),
+#endif
 };
 
 static bool find_pdmode(SkXfermode::Mode src, SkPorterDuff::Mode* dst) {
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index 5497734..1c0b269 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -345,7 +345,7 @@
 // static
 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
         uint32_t fontID, bool perGlyphInfo) {
-#if defined(SK_BUILD_FOR_MAC)
+#if defined(SK_BUILD_FOR_MAC) || defined(ANDROID)
     return NULL;
 #else
     SkAutoMutexAcquire ac(gFTMutex);
@@ -540,6 +540,21 @@
     rec->setHinting(h);
 }
 
+#ifdef ANDROID
+uint32_t SkFontHost::GetUnitsPerEm(SkFontID fontID) {
+    SkAutoMutexAcquire ac(gFTMutex);
+    SkFaceRec *rec = ref_ft_face(fontID);
+    uint16_t unitsPerEm = 0;
+
+    if (rec != NULL && rec->fFace != NULL) {
+        unitsPerEm = rec->fFace->units_per_EM;
+        unref_ft_face(rec->fFace);
+    }
+
+    return (uint32_t)unitsPerEm;
+}
+#endif
+
 SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
         : SkScalerContext(desc) {
     SkAutoMutexAcquire  ac(gFTMutex);
diff --git a/src/utils/SkCamera.cpp b/src/utils/SkCamera.cpp
index b02499f..87d2aad 100644
--- a/src/utils/SkCamera.cpp
+++ b/src/utils/SkCamera.cpp
@@ -400,6 +400,18 @@
     fRec = next;
 }
 
+#ifdef ANDROID
+void Sk3DView::setCameraLocation(SkScalar x, SkScalar y, SkScalar z)
+{
+    // the camera location is passed in inches, set in pt
+    SkScalar lz = z * SkFloatToScalar(72.0f);
+    fCamera.fLocation.set(x * SkFloatToScalar(72.0f), y * SkFloatToScalar(72.0f), lz);
+    fCamera.fObserver.set(0, 0, lz);
+    fCamera.update();
+    
+}
+#endif
+
 void Sk3DView::translate(SkScalar x, SkScalar y, SkScalar z)
 {
     fRec->fMatrix.preTranslate(x, y, z);