add script to scrape glyph usage in drawText calls

git-svn-id: http://skia.googlecode.com/svn/trunk@9353 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/utils/SkLua.h b/include/utils/SkLua.h
index f24f8a5..c609746 100644
--- a/include/utils/SkLua.h
+++ b/include/utils/SkLua.h
@@ -41,8 +41,11 @@
 
     void pushBool(bool, const char tableKey[] = NULL);
     void pushString(const char[], const char tableKey[] = NULL);
+    void pushString(const char[], size_t len, const char tableKey[] = NULL);
     void pushString(const SkString&, const char tableKey[] = NULL);
+    void pushArrayU16(const uint16_t[], int count, const char tableKey[] = NULL);
     void pushColor(SkColor, const char tableKey[] = NULL);
+    void pushU32(uint32_t, const char tableKey[] = NULL);
     void pushScalar(SkScalar, const char tableKey[] = NULL);
     void pushRect(const SkRect&, const char tableKey[] = NULL);
     void pushRRect(const SkRRect&, const char tableKey[] = NULL);
diff --git a/src/utils/SkLua.cpp b/src/utils/SkLua.cpp
index 9aef50e..bd453e3 100644
--- a/src/utils/SkLua.cpp
+++ b/src/utils/SkLua.cpp
@@ -12,6 +12,7 @@
 #include "SkMatrix.h"
 #include "SkRRect.h"
 #include "SkString.h"
+#include "SkTypeface.h"
 
 extern "C" {
     #include "lua.h"
@@ -120,6 +121,11 @@
     lua_setfield(L, -2, key);
 }
 
+static void setarray_number(lua_State* L, int index, double value) {
+    lua_pushnumber(L, value);
+    lua_rawseti(L, -2, index);
+}
+
 void SkLua::pushBool(bool value, const char key[]) {
     lua_pushboolean(fL, value);
     CHECK_SETFIELD(key);
@@ -130,6 +136,13 @@
     CHECK_SETFIELD(key);
 }
 
+void SkLua::pushString(const char str[], size_t length, const char key[]) {
+    // TODO: how to do this w/o making a copy?
+    SkString s(str, length);
+    lua_pushstring(fL, s.c_str());
+    CHECK_SETFIELD(key);
+}
+
 void SkLua::pushString(const SkString& str, const char key[]) {
     lua_pushstring(fL, str.c_str());
     CHECK_SETFIELD(key);
@@ -144,11 +157,25 @@
     CHECK_SETFIELD(key);
 }
 
+void SkLua::pushU32(uint32_t value, const char key[]) {
+    lua_pushnumber(fL, (double)value);
+    CHECK_SETFIELD(key);
+}
+
 void SkLua::pushScalar(SkScalar value, const char key[]) {
     lua_pushnumber(fL, SkScalarToLua(value));
     CHECK_SETFIELD(key);
 }
 
+void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
+    lua_newtable(fL);
+    for (int i = 0; i < count; ++i) {
+        // make it base-1 to match lua convention
+        setarray_number(fL, i + 1, (double)array[i]);
+    }
+    CHECK_SETFIELD(key);
+}
+
 void SkLua::pushRect(const SkRect& r, const char key[]) {
     lua_newtable(fL);
     setfield_number(fL, "left", SkScalarToLua(r.fLeft));
@@ -314,6 +341,22 @@
     return 0;
 }
 
+static int lpaint_getTextSize(lua_State* L) {
+    SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSize());
+    return 1;
+}
+
+static int lpaint_setTextSize(lua_State* L) {
+    get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
+    return 0;
+}
+
+static int lpaint_getFontID(lua_State* L) {
+    SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
+    SkLua(L).pushU32(SkTypeface::UniqueID(face));
+    return 1;
+}
+
 static int lpaint_gc(lua_State* L) {
     get_obj<SkPaint>(L, 1)->~SkPaint();
     return 0;
@@ -324,6 +367,9 @@
     { "setAntiAlias", lpaint_setAntiAlias },
     { "getColor", lpaint_getColor },
     { "setColor", lpaint_setColor },
+    { "getTextSize", lpaint_getTextSize },
+    { "setTextSize", lpaint_setTextSize },
+    { "getFontID", lpaint_getFontID },
     { "__gc", lpaint_gc },
     { NULL, NULL }
 };
diff --git a/src/utils/SkLuaCanvas.cpp b/src/utils/SkLuaCanvas.cpp
index d3ecd74..1299a0e 100644
--- a/src/utils/SkLuaCanvas.cpp
+++ b/src/utils/SkLuaCanvas.cpp
@@ -34,12 +34,36 @@
         lua_settop(L, -1);
     }
 
+    void pushEncodedText(SkPaint::TextEncoding, const void*, size_t);
+
 private:
     typedef SkLua INHERITED;
 };
 
 #define AUTO_LUA(verb)  AutoCallLua lua(fL, fFunc.c_str(), verb)
 
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AutoCallLua::pushEncodedText(SkPaint::TextEncoding enc, const void* text,
+                                  size_t length) {
+    switch (enc) {
+        case SkPaint::kUTF8_TextEncoding:
+            this->pushString((const char*)text, length, "text");
+            break;
+        case SkPaint::kUTF16_TextEncoding: {
+            SkString str;
+            str.setUTF16((const uint16_t*)text, length);
+            this->pushString(str, "text");
+        } break;
+        case SkPaint::kGlyphID_TextEncoding:
+            this->pushArrayU16((const uint16_t*)text, length >> 1, "glyphs");
+            break;
+        case SkPaint::kUTF32_TextEncoding:
+            break;
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 void SkLuaCanvas::pushThis() {
@@ -216,12 +240,14 @@
 void SkLuaCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
                              SkScalar y, const SkPaint& paint) {
     AUTO_LUA("drawText");
+    lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
     lua.pushPaint(paint, "paint");
 }
 
 void SkLuaCanvas::drawPosText(const void* text, size_t byteLength,
                                 const SkPoint pos[], const SkPaint& paint) {
     AUTO_LUA("drawPosText");
+    lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
     lua.pushPaint(paint, "paint");
 }
 
@@ -229,6 +255,7 @@
                                  const SkScalar xpos[], SkScalar constY,
                                  const SkPaint& paint) {
     AUTO_LUA("drawPosTextH");
+    lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
     lua.pushPaint(paint, "paint");
 }
 
@@ -237,6 +264,7 @@
                                    const SkPaint& paint) {
     AUTO_LUA("drawTextOnPath");
     lua.pushPath(path, "path");
+    lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
     lua.pushPaint(paint, "paint");
 }
 
diff --git a/tools/lua/glyph-usage.lua b/tools/lua/glyph-usage.lua
new file mode 100644
index 0000000..2b0c0e1
--- /dev/null
+++ b/tools/lua/glyph-usage.lua
@@ -0,0 +1,113 @@
+function tostr(t)
+    local str = ""
+    for k, v in next, t do
+        if #str > 0 then
+            str = str .. ", "
+        end
+        if type(k) == "number" then
+            str = str .. "[" .. k .. "] = "
+        else
+            str = str .. tostring(k) .. " = "
+        end
+        if type(v) == "table" then
+            str = str .. "{ " .. tostr(v) .. " }"
+        else
+            str = str .. tostring(v)
+        end
+    end
+    return str
+end
+
+local canvas        -- holds the current canvas (from startcanvas())
+
+--[[
+    startcanvas() is called at the start of each picture file, passing the
+    canvas that we will be drawing into, and the name of the file.
+    
+    Following this call, there will be some number of calls to accumulate(t)
+    where t is a table of parameters that were passed to that draw-op.
+    
+        t.verb is a string holding the name of the draw-op (e.g. "drawRect")
+    
+    when a given picture is done, we call endcanvas(canvas, fileName)
+]]
+function sk_scrape_startcanvas(c, fileName)
+    canvas = c
+end
+
+--[[
+    Called when the current canvas is done drawing.
+]]
+function sk_scrape_endcanvas(c, fileName)
+    canvas = nil
+end
+
+--[[
+    Called with the parameters to each canvas.draw call, where canvas is the
+    current canvas as set by startcanvas()
+]]
+
+function round(x, mul)
+    mul = mul or 1
+    return math.floor(x * mul + 0.5) / mul
+end
+
+local strikes = {}  -- [fontID_pointsize] = [] unique glyphs
+
+function make_strike_key(paint)
+    return paint:getFontID() * 1000 + paint:getTextSize()
+end
+
+-- array is an array of bools (true), using glyphID as the index
+-- other is just an array[1...N] of numbers (glyphIDs)
+function array_union(array, other)
+    for k, v in next, other do
+        array[v] = true;
+    end
+end
+
+function array_count(array)
+    local n = 0
+    for k in next, array do
+        n = n + 1
+    end
+    return n
+end
+
+function sk_scrape_accumulate(t)
+    verb = t.verb;
+    if verb == "drawPosText" or verb == "drawPosTextH" then
+        if t.glyphs then
+            local key = make_strike_key(t.paint)
+            strikes[key] = strikes[key] or {}
+            array_union(strikes[key], t.glyphs)
+        end
+    end
+end
+
+--[[
+    lua_pictures will call this function after all of the pictures have been
+    "accumulated".
+]]
+function sk_scrape_summarize()
+    local totalCount = 0
+    local strikeCount = 0
+    local min, max = 0, 0
+
+    for k, v in next, strikes do
+        local fontID = round(k / 1000)
+        local size = k - fontID * 1000
+        local count = array_count(v)
+
+        io.write("fontID = ", fontID, ", size = ", size, ", entries = ", count, "\n");
+        
+        min = math.min(min, count)
+        max = math.max(max, count)
+        totalCount = totalCount + count
+        strikeCount = strikeCount + 1
+    end
+    local ave = round(totalCount / strikeCount)
+
+    io.write("\n", "unique glyphs: min = ", min, ", max = ", max, ", ave = ", ave, "\n");
+end
+