Home | History | Annotate | Download | only in lua
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "LazyDecodeBitmap.h"
      9 #include "SkLua.h"
     10 #include "SkLuaCanvas.h"
     11 #include "SkPicture.h"
     12 #include "SkCommandLineFlags.h"
     13 #include "SkGraphics.h"
     14 #include "SkStream.h"
     15 #include "SkData.h"
     16 #include "picture_utils.h"
     17 #include "SkOSFile.h"
     18 #include "SkImageDecoder.h"
     19 
     20 extern "C" {
     21     #include "lua.h"
     22     #include "lualib.h"
     23     #include "lauxlib.h"
     24 }
     25 
     26 static const char gStartCanvasFunc[] = "sk_scrape_startcanvas";
     27 static const char gEndCanvasFunc[] = "sk_scrape_endcanvas";
     28 static const char gAccumulateFunc[] = "sk_scrape_accumulate";
     29 static const char gSummarizeFunc[] = "sk_scrape_summarize";
     30 
     31 // Example usage for the modulo flag:
     32 // for i in {0..5}; do lua_pictures --skpPath SKP_PATH -l YOUR_SCRIPT --modulo $i 6 &; done
     33 DEFINE_string(modulo, "", "[--modulo <remainder> <divisor>]: only run tests for which "
     34               "testIndex %% divisor == remainder.");
     35 DEFINE_string2(skpPath, r, "", "Read this .skp file or .skp files from this dir");
     36 DEFINE_string2(luaFile, l, "", "File containing lua script to run");
     37 DEFINE_string2(headCode, s, "", "Optional lua code to call at beginning");
     38 DEFINE_string2(tailFunc, s, "", "Optional lua function to call at end");
     39 
     40 static SkPicture* load_picture(const char path[]) {
     41     SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
     42     SkPicture* pic = NULL;
     43     if (stream.get()) {
     44         pic = SkPicture::CreateFromStream(stream.get(), &sk_tools::LazyDecodeBitmap);
     45     }
     46     return pic;
     47 }
     48 
     49 static SkData* read_into_data(const char file[]) {
     50     SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(file));
     51     if (!stream.get()) {
     52         return SkData::NewEmpty();
     53     }
     54     size_t len = stream->getLength();
     55     void* buffer = sk_malloc_throw(len);
     56     stream->read(buffer, len);
     57     return SkData::NewFromMalloc(buffer, len);
     58 }
     59 
     60 static void call_canvas(lua_State* L, SkLuaCanvas* canvas,
     61                         const char pictureFile[], const char funcName[]) {
     62     lua_getglobal(L, funcName);
     63     if (!lua_isfunction(L, -1)) {
     64         int t = lua_type(L, -1);
     65         SkDebugf("--- expected %s function %d, ignoring.\n", funcName, t);
     66         lua_settop(L, -2);
     67     } else {
     68         canvas->pushThis();
     69         lua_pushstring(L, pictureFile);
     70         if (lua_pcall(L, 2, 0, 0) != LUA_OK) {
     71             SkDebugf("lua err: %s\n", lua_tostring(L, -1));
     72         }
     73     }
     74 }
     75 
     76 int tool_main(int argc, char** argv);
     77 int tool_main(int argc, char** argv) {
     78     SkCommandLineFlags::SetUsage("apply lua script to .skp files.");
     79     SkCommandLineFlags::Parse(argc, argv);
     80 
     81     if (FLAGS_skpPath.isEmpty()) {
     82         SkDebugf(".skp files or directories are required.\n");
     83         exit(-1);
     84     }
     85     if (FLAGS_luaFile.isEmpty()) {
     86         SkDebugf("missing luaFile(s)\n");
     87         exit(-1);
     88     }
     89 
     90     const char* summary = gSummarizeFunc;
     91     if (!FLAGS_tailFunc.isEmpty()) {
     92         summary = FLAGS_tailFunc[0];
     93     }
     94 
     95     SkAutoGraphics ag;
     96     SkLua L(summary);
     97 
     98     for (int i = 0; i < FLAGS_luaFile.count(); ++i) {
     99         SkAutoDataUnref data(read_into_data(FLAGS_luaFile[i]));
    100         SkDebugf("loading %s...\n", FLAGS_luaFile[i]);
    101         if (!L.runCode(data->data(), data->size())) {
    102             SkDebugf("failed to load luaFile %s\n", FLAGS_luaFile[i]);
    103             exit(-1);
    104         }
    105     }
    106 
    107     if (!FLAGS_headCode.isEmpty()) {
    108         L.runCode(FLAGS_headCode[0]);
    109     }
    110 
    111     int moduloRemainder = -1;
    112     int moduloDivisor = -1;
    113     SkString moduloStr;
    114 
    115     if (FLAGS_modulo.count() == 2) {
    116         moduloRemainder = atoi(FLAGS_modulo[0]);
    117         moduloDivisor = atoi(FLAGS_modulo[1]);
    118         if (moduloRemainder < 0 || moduloDivisor <= 0 || moduloRemainder >= moduloDivisor) {
    119             SkDebugf("invalid modulo values.\n");
    120             return -1;
    121         }
    122     }
    123 
    124     for (int i = 0; i < FLAGS_skpPath.count(); i ++) {
    125         SkTArray<SkString> paths;
    126         if (sk_isdir(FLAGS_skpPath[i])) {
    127             // Add all .skp in this directory.
    128             const SkString directory(FLAGS_skpPath[i]);
    129             SkString filename;
    130             SkOSFile::Iter iter(FLAGS_skpPath[i], "skp");
    131             while(iter.next(&filename)) {
    132                 sk_tools::make_filepath(&paths.push_back(), directory, filename);
    133             }
    134         } else {
    135             // Add this as an .skp itself.
    136             paths.push_back() = FLAGS_skpPath[i];
    137         }
    138 
    139         for (int i = 0; i < paths.count(); i++) {
    140             if (moduloRemainder >= 0) {
    141                 if ((i % moduloDivisor) != moduloRemainder) {
    142                     continue;
    143                 }
    144                 moduloStr.printf("[%d.%d] ", i, moduloDivisor);
    145             }
    146             const char* path = paths[i].c_str();
    147             SkDebugf("scraping %s %s\n", path, moduloStr.c_str());
    148 
    149             SkAutoTUnref<SkPicture> pic(load_picture(path));
    150             if (pic.get()) {
    151                 SkAutoTUnref<SkLuaCanvas> canvas(
    152                                     new SkLuaCanvas(pic->width(), pic->height(),
    153                                                     L.get(), gAccumulateFunc));
    154 
    155                 call_canvas(L.get(), canvas.get(), path, gStartCanvasFunc);
    156                 canvas->drawPicture(*pic);
    157                 call_canvas(L.get(), canvas.get(), path, gEndCanvasFunc);
    158 
    159             } else {
    160                 SkDebugf("failed to load\n");
    161             }
    162         }
    163     }
    164     return 0;
    165 }
    166 
    167 #if !defined SK_BUILD_FOR_IOS
    168 int main(int argc, char * const argv[]) {
    169     return tool_main(argc, (char**) argv);
    170 }
    171 #endif
    172