am c27ee87c: Reconcile with jb-release

* commit 'c27ee87c8da93b6d609be1be18eaa0f0c7d07e98':
diff --git a/Android.mk b/Android.mk
index 08cf6f8..846c157 100644
--- a/Android.mk
+++ b/Android.mk
@@ -295,6 +295,7 @@
 	$(LOCAL_PATH)/include/config \
 	$(LOCAL_PATH)/include/effects \
 	$(LOCAL_PATH)/include/images \
+	$(LOCAL_PATH)/include/ports \
 	$(LOCAL_PATH)/include/utils \
 	$(LOCAL_PATH)/include/xml \
 	external/freetype/include \
diff --git a/ThirdPartyProject.prop b/ThirdPartyProject.prop
deleted file mode 100644
index 6bd7584..0000000
--- a/ThirdPartyProject.prop
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright 2010 Google Inc. All Rights Reserved.
-#Fri Jul 16 10:03:09 PDT 2010
-currentVersion=Unknown
-version=Unknown
-isNative=true
-name=skia
-keywords=skia
-onDevice=true
-homepage=http\://code.google.com/p/skia/
diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h
index 29679d6..9bcf601 100644
--- a/include/core/SkScalerContext.h
+++ b/include/core/SkScalerContext.h
@@ -15,6 +15,7 @@
 #include "SkPaint.h"
 #include "SkPath.h"
 #include "SkPoint.h"
+#include "SkTypeface.h"
 
 //#define SK_USE_COLOR_LUMINANCE
 
@@ -299,6 +300,19 @@
                                SkPaint::FontMetrics* mY);
 
 #ifdef SK_BUILD_FOR_ANDROID
+    // This function must be public for SkTypeface_android.h, but should not be
+    // called by other callers
+    SkFontID findTypefaceIdForChar(SkUnichar uni) {
+        SkScalerContext* ctx = this;
+        while (NULL != ctx) {
+            if (ctx->generateCharToGlyph(uni)) {
+                return ctx->fRec.fFontID;
+            }
+            ctx = ctx->getNextContext();
+        }
+        return 0;
+    }
+
     unsigned getBaseGlyphCount(SkUnichar charCode);
 #endif
 
diff --git a/include/ports/SkTypeface_android.h b/include/ports/SkTypeface_android.h
index 1a02a55..3471a94 100644
--- a/include/ports/SkTypeface_android.h
+++ b/include/ports/SkTypeface_android.h
@@ -29,6 +29,28 @@
     kFallbackScriptNumber
 };
 
+#define SkTypeface_ValidScript(s) (s >= 0 && s < kFallbackScriptNumber)
 
-SK_API SkTypeface* SkCreateTypefaceForScript(FallbackScripts script) {return NULL; }
+/**
+ *  Return a new typeface for a fallback script. If the script is
+ *  not valid, or can not map to a font, returns null.
+ *  @param  script  The script id.
+ *  @return reference to the matching typeface. Caller must call
+ *          unref() when they are done.
+ */
+SK_API SkTypeface* SkCreateTypefaceForScript(FallbackScripts script);
+
+/**
+ *  Return the string representation for the fallback script on Android.
+ *  If the script is not valid, returns null.
+ */
+SK_API const char* SkGetFallbackScriptID(FallbackScripts script);
+
+/**
+ *  Return the fallback script enum for the ID on Android.
+ *  If the ID is not valid, or can not map to a fallback
+ *  script, returns kFallbackScriptNumber.
+ */
+SK_API FallbackScripts SkGetFallbackScriptFromID(const char* id);
+
 #endif
diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h
index 2895c54..23f3c55 100644
--- a/src/core/SkGlyphCache.h
+++ b/src/core/SkGlyphCache.h
@@ -123,6 +123,8 @@
     //  call the proc)
     void removeAuxProc(void (*auxProc)(void*));
 
+    SkScalerContext* getScalerContext() const { return fScalerContext; }
+
     /** Call proc on all cache entries, stopping early if proc returns true.
         The proc should not create or delete caches, since it could produce
         deadlock.
diff --git a/src/images/SkImageDecoder_libwebp.cpp b/src/images/SkImageDecoder_libwebp.cpp
index 3e416cc..b2aea24 100644
--- a/src/images/SkImageDecoder_libwebp.cpp
+++ b/src/images/SkImageDecoder_libwebp.cpp
@@ -56,20 +56,29 @@
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
-static const size_t WEBP_VP8_HEADER_SIZE = 30;
+static const size_t WEBP_VP8_HEADER_SIZE = 64;
 static const size_t WEBP_IDECODE_BUFFER_SZ = (1 << 16);
 
 // Parse headers of RIFF container, and check for valid Webp (VP8) content.
-static bool webp_parse_header(SkStream* stream, int* width, int* height) {
+static bool webp_parse_header(SkStream* stream, int* width, int* height,
+                              int* alpha) {
     unsigned char buffer[WEBP_VP8_HEADER_SIZE];
+    const uint32_t contentSize = stream->getLength();
     const size_t len = stream->read(buffer, WEBP_VP8_HEADER_SIZE);
-    if (len != WEBP_VP8_HEADER_SIZE) {
+    const uint32_t read_bytes = (contentSize < WEBP_VP8_HEADER_SIZE) ?
+        contentSize : WEBP_VP8_HEADER_SIZE;
+    if (len != read_bytes) {
         return false; // can't read enough
     }
 
-    if (WebPGetInfo(buffer, WEBP_VP8_HEADER_SIZE, width, height) == 0) {
+    WebPBitstreamFeatures features;
+    VP8StatusCode status = WebPGetFeatures(buffer, read_bytes, &features);
+    if (status != VP8_STATUS_OK) {
         return false; // Invalid WebP file.
     }
+    *width = features.width;
+    *height = features.height;
+    *alpha = features.has_alpha;
 
     // sanity check for image size that's about to be decoded.
     {
@@ -102,6 +111,7 @@
     SkStream *inputStream;
     int origWidth;
     int origHeight;
+    int hasAlpha;
 };
 
 //////////////////////////////////////////////////////////////////////////
@@ -160,10 +170,8 @@
 
     stream->rewind();
     const uint32_t contentSize = stream->getLength();
-    uint32_t read_buffer_size = contentSize;
-    if (read_buffer_size > WEBP_IDECODE_BUFFER_SZ) {
-        read_buffer_size = WEBP_IDECODE_BUFFER_SZ;
-    }
+    const uint32_t read_buffer_size = (contentSize < WEBP_IDECODE_BUFFER_SZ) ?
+        contentSize : WEBP_IDECODE_BUFFER_SZ;
     SkAutoMalloc srcStorage(read_buffer_size);
     unsigned char* input = (uint8_t*)srcStorage.get();
     if (input == NULL) {
@@ -175,8 +183,8 @@
     uint32_t bytes_remaining = contentSize;
     while (bytes_remaining > 0) {
         const uint32_t bytes_to_read =
-            (bytes_remaining > WEBP_IDECODE_BUFFER_SZ) ?
-                WEBP_IDECODE_BUFFER_SZ : bytes_remaining;
+            (bytes_remaining < WEBP_IDECODE_BUFFER_SZ) ?
+                bytes_remaining : WEBP_IDECODE_BUFFER_SZ;
 
         const size_t bytes_read = stream->read(input, bytes_to_read);
         if (bytes_read == 0) {
@@ -201,9 +209,9 @@
     }
 }
 
-static bool webp_get_config_resize_crop(WebPDecoderConfig& config,
-                                        SkBitmap* decodedBitmap,
-                                        SkIRect region) {
+static bool webp_get_config_resize(WebPDecoderConfig& config,
+                                   SkBitmap* decodedBitmap,
+                                   int width, int height) {
     WEBP_CSP_MODE mode = webp_decode_mode(decodedBitmap);
     if (mode == MODE_LAST) {
         return false;
@@ -219,53 +227,34 @@
     config.output.u.RGBA.size = decodedBitmap->getSize();
     config.output.is_external_memory = 1;
 
+    if (width != decodedBitmap->width() ||
+        height != decodedBitmap->height()) {
+        config.options.use_scaling = 1;
+        config.options.scaled_width = decodedBitmap->width();
+        config.options.scaled_height = decodedBitmap->height();
+    }
+
+    return true;
+}
+
+static bool webp_get_config_resize_crop(WebPDecoderConfig& config,
+                                        SkBitmap* decodedBitmap,
+                                        SkIRect region) {
+
+    if (!webp_get_config_resize(config, decodedBitmap,
+                                region.width(), region.height())) return false;
+
     config.options.use_cropping = 1;
     config.options.crop_left = region.fLeft;
     config.options.crop_top = region.fTop;
     config.options.crop_width = region.width();
     config.options.crop_height = region.height();
 
-    if (region.width() != decodedBitmap->width() ||
-        region.height() != decodedBitmap->height()) {
-        config.options.use_scaling = 1;
-        config.options.scaled_width = decodedBitmap->width();
-        config.options.scaled_height = decodedBitmap->height();
-    }
-
-    return true;
-}
-
-static bool webp_get_config_resize(WebPDecoderConfig& config,
-                                   SkBitmap* decodedBitmap, int origWidth,
-                                   int origHeight) {
-    WEBP_CSP_MODE mode = webp_decode_mode(decodedBitmap);
-    if (mode == MODE_LAST) {
-        return false;
-    }
-
-    if (WebPInitDecoderConfig(&config) == 0) {
-        return false;
-    }
-
-    config.output.colorspace = mode;
-    config.output.u.RGBA.rgba = (uint8_t*)decodedBitmap->getPixels();
-    config.output.u.RGBA.stride = decodedBitmap->rowBytes();
-    config.output.u.RGBA.size = decodedBitmap->getSize();
-    config.output.is_external_memory = 1;
-
-    if (origWidth != decodedBitmap->width() ||
-        origHeight != decodedBitmap->height()) {
-        config.options.use_scaling = 1;
-        config.options.scaled_width = decodedBitmap->width();
-        config.options.scaled_height = decodedBitmap->height();
-    }
-
     return true;
 }
 
 bool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap,
                                          int width, int height) {
-    bool hasAlpha = false;
     SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, hasAlpha);
 
     // YUV converter supports output in RGB565, RGBA4444 and RGBA8888 formats.
@@ -286,16 +275,15 @@
 
     decodedBitmap->setConfig(config, width, height, 0);
 
-    // Current WEBP specification has no support for alpha layer.
-    decodedBitmap->setIsOpaque(true);
+    decodedBitmap->setIsOpaque(!hasAlpha);
 
     return true;
 }
 
 bool SkWEBPImageDecoder::onBuildTileIndex(SkStream* stream,
                                           int *width, int *height) {
-    int origWidth, origHeight;
-    if (!webp_parse_header(stream, &origWidth, &origHeight)) {
+    int origWidth, origHeight, hasAlpha;
+    if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) {
         return false;
     }
 
@@ -306,11 +294,12 @@
     this->inputStream = stream;
     this->origWidth = origWidth;
     this->origHeight = origHeight;
+    this->hasAlpha = hasAlpha;
 
     return true;
 }
 
-static bool isConfigCompatiable(SkBitmap* bitmap) {
+static bool isConfigCompatible(SkBitmap* bitmap) {
     SkBitmap::Config config = bitmap->config();
     return config == SkBitmap::kARGB_4444_Config ||
            config == SkBitmap::kRGB_565_Config ||
@@ -338,9 +327,9 @@
     //   3. bitmap's size is same as the required region (after sampled)
     bool directDecode = (rect == region) &&
                         (decodedBitmap->isNull() ||
-                         isConfigCompatiable(decodedBitmap) &&
+                         (isConfigCompatible(decodedBitmap) &&
                          (decodedBitmap->width() == width) &&
-                         (decodedBitmap->height() == height));
+                         (decodedBitmap->height() == height)));
     SkTScopedPtr<SkBitmap> adb;
     SkBitmap *bitmap = decodedBitmap;
 
@@ -394,10 +383,11 @@
     AutoTimeMillis atm("WEBP Decode");
 #endif
 
-    int origWidth, origHeight;
-    if (!webp_parse_header(stream, &origWidth, &origHeight)) {
+    int origWidth, origHeight, hasAlpha;
+    if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) {
         return false;
     }
+    this->hasAlpha = hasAlpha;
 
     const int sampleSize = this->getSampleSize();
     SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
@@ -568,8 +558,8 @@
 #include "SkTRegistry.h"
 
 static SkImageDecoder* DFactory(SkStream* stream) {
-    int width, height;
-    if (!webp_parse_header(stream, &width, &height)) {
+    int width, height, hasAlpha;
+    if (!webp_parse_header(stream, &width, &height, &hasAlpha)) {
         return false;
     }
 
diff --git a/src/ports/SkFontHost_android.cpp b/src/ports/SkFontHost_android.cpp
index 2c58079..afd0ebe 100644
--- a/src/ports/SkFontHost_android.cpp
+++ b/src/ports/SkFontHost_android.cpp
@@ -27,6 +27,9 @@
 #include "FontHostConfiguration_android.h"
 #include <stdio.h>
 #include <string.h>
+#include "SkGlyphCache.h"
+#include "SkTypeface_android.h"
+
 
 //#define SkDEBUGF(args       )       SkDebugf args
 
@@ -958,3 +961,135 @@
     stream->unref();
     return face;
 }
+
+///////////////////////////////////////////////////////////////////////////////
+// Function from SkTypeface_android.h
+///////////////////////////////////////////////////////////////////////////////
+
+struct FBScriptInfo {
+    const FallbackScripts fScript;
+    const char* fScriptID;
+    const SkTypeface::Style fStyle;
+    const SkUnichar fChar; // representative character for that script type
+    SkFontID fFontID;
+};
+
+#define SK_DEFINE_SCRIPT_ENTRY(script, style, unichar) \
+    { script, #script, style, unichar, 0 }
+
+static FBScriptInfo gFBScriptInfo[] = {
+    SK_DEFINE_SCRIPT_ENTRY(kArabic_FallbackScript,        SkTypeface::kNormal, 0x0600),
+    SK_DEFINE_SCRIPT_ENTRY(kArmenian_FallbackScript,      SkTypeface::kNormal, 0x0531),
+    SK_DEFINE_SCRIPT_ENTRY(kBengali_FallbackScript,       SkTypeface::kNormal, 0x0981),
+    SK_DEFINE_SCRIPT_ENTRY(kDevanagari_FallbackScript,    SkTypeface::kNormal, 0x0901),
+    SK_DEFINE_SCRIPT_ENTRY(kEthiopic_FallbackScript,      SkTypeface::kNormal, 0x1200),
+    SK_DEFINE_SCRIPT_ENTRY(kGeorgian_FallbackScript,      SkTypeface::kNormal, 0x10A0),
+    SK_DEFINE_SCRIPT_ENTRY(kHebrewRegular_FallbackScript, SkTypeface::kNormal, 0x0591),
+    SK_DEFINE_SCRIPT_ENTRY(kHebrewBold_FallbackScript,    SkTypeface::kBold,   0x0591),
+    SK_DEFINE_SCRIPT_ENTRY(kKannada_FallbackScript,       SkTypeface::kNormal, 0x0C90),
+    SK_DEFINE_SCRIPT_ENTRY(kMalayalam_FallbackScript,     SkTypeface::kNormal, 0x0D10),
+    SK_DEFINE_SCRIPT_ENTRY(kTamilRegular_FallbackScript,  SkTypeface::kNormal, 0x0B82),
+    SK_DEFINE_SCRIPT_ENTRY(kTamilBold_FallbackScript,     SkTypeface::kBold,   0x0B82),
+    SK_DEFINE_SCRIPT_ENTRY(kThai_FallbackScript,          SkTypeface::kNormal, 0x0E01),
+    SK_DEFINE_SCRIPT_ENTRY(kTelugu_FallbackScript,        SkTypeface::kNormal, 0x0C10),
+};
+
+static bool gFBScriptInitialized = false;
+static const int gFBScriptInfoCount = sizeof(gFBScriptInfo) / sizeof(FBScriptInfo);
+
+// ensure that if any value is added to the public enum it is also added here
+SK_COMPILE_ASSERT(gFBScriptInfoCount == kFallbackScriptNumber, FBScript_count_mismatch);
+
+
+// this function can't be called if the gFamilyHeadAndNameListMutex is already locked
+static SkFontID findFontIDForChar(SkUnichar uni, SkTypeface::Style style) {
+    gFamilyHeadAndNameListMutex.acquire();
+    SkTypeface* face = findBestFaceLocked(gDefaultFamily, style);
+    gFamilyHeadAndNameListMutex.release();
+    if (!face) {
+        return 0;
+    }
+
+    SkPaint paint;
+    paint.setTypeface(face);
+    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+
+    SkAutoGlyphCache autoCache(paint, NULL);
+    SkGlyphCache*    cache = autoCache.getCache();
+    SkFontID         fontID = 0;
+
+    SkScalerContext* ctx = cache->getScalerContext();
+    if (ctx) {
+        return ctx->findTypefaceIdForChar(uni);
+    }
+    return 0;
+}
+
+// this function can't be called if the gFamilyHeadAndNameListMutex is already locked
+static void initFBScriptInfo() {
+    if (gFBScriptInitialized) {
+        return;
+    }
+
+    // ensure the system fonts are loaded
+    gFamilyHeadAndNameListMutex.acquire();
+    loadSystemFontsLocked();
+    gFamilyHeadAndNameListMutex.release();
+
+    for (int i = 0; i < gFBScriptInfoCount; i++) {
+        FBScriptInfo& scriptInfo = gFBScriptInfo[i];
+        // selects the best available style for the desired font. However, if
+        // bold is requested and no bold font exists for the typeface containing
+        // the character the next best style is chosen (e.g. normal).
+        scriptInfo.fFontID = findFontIDForChar(scriptInfo.fChar, scriptInfo.fStyle);
+        SkDEBUGF(("gFBScriptInfo[%s] --> %d", scriptInfo.fScriptID, scriptInfo.fFontID));
+    }
+    // mark the value as initialized so we don't repeat our work unnecessarily
+    gFBScriptInitialized = true;
+}
+
+SkTypeface* SkCreateTypefaceForScript(FallbackScripts script) {
+    if (!SkTypeface_ValidScript(script)) {
+        return NULL;
+    }
+
+    // ensure that our table is populated
+    initFBScriptInfo();
+
+    FBScriptInfo& scriptInfo = gFBScriptInfo[script];
+
+    // ensure the element with that index actually maps to the correct script
+    SkASSERT(scriptInfo.fScript == script);
+
+    // if a suitable script could not be found then return NULL
+    if (scriptInfo.fFontID == 0) {
+        return NULL;
+    }
+
+    SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
+
+    // retrieve the typeface the corresponds to this fontID
+    SkTypeface* tf = findFromUniqueIDLocked(scriptInfo.fFontID);
+    // we ref(), since the semantic is to return a new instance
+    tf->ref();
+    return tf;
+}
+
+const char* SkGetFallbackScriptID(FallbackScripts script) {
+    for (int i = 0; i < gFBScriptInfoCount; i++) {
+        if (gFBScriptInfo[i].fScript == script) {
+            return gFBScriptInfo[i].fScriptID;
+        }
+    }
+    return NULL;
+}
+
+FallbackScripts SkGetFallbackScriptFromID(const char* id) {
+    for (int i = 0; i < gFBScriptInfoCount; i++) {
+        if (strcmp(gFBScriptInfo[i].fScriptID, id) == 0) {
+            return gFBScriptInfo[i].fScript;
+        }
+    }
+    return kFallbackScriptNumber; // Use kFallbackScriptNumber as an invalid value.
+}
+