diff options
-rw-r--r-- | BUILD.gn | 2 | ||||
-rw-r--r-- | tools/ok.cpp | 243 | ||||
-rw-r--r-- | tools/ok.h | 54 | ||||
-rw-r--r-- | tools/ok_dsts.cpp | 33 | ||||
-rw-r--r-- | tools/ok_srcs.cpp | 99 |
5 files changed, 241 insertions, 190 deletions
@@ -1152,6 +1152,8 @@ if (skia_enable_tools) { test_app("ok") { sources = [ "tools/ok.cpp", + "tools/ok_dsts.cpp", + "tools/ok_srcs.cpp", ] deps = [ ":gm", diff --git a/tools/ok.cpp b/tools/ok.cpp index db82b2f028..bfef28f0a5 100644 --- a/tools/ok.cpp +++ b/tools/ok.cpp @@ -11,17 +11,11 @@ #include "SkGraphics.h" #include "SkOSFile.h" -#include "SkPicture.h" -#include "SkSurface.h" -#include "gm.h" +#include "ok.h" #include <chrono> -#include <functional> #include <future> #include <list> -#include <map> -#include <memory> #include <regex> -#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <thread> @@ -161,178 +155,17 @@ struct ThreadEngine : Engine { }; #endif -struct Src { - virtual ~Src() {} - virtual std::string name() = 0; - virtual SkISize size() = 0; - virtual void draw(SkCanvas*) = 0; -}; - -struct Stream { - virtual ~Stream() {} - virtual std::unique_ptr<Src> next() = 0; -}; - -struct Options { - std::map<std::string, std::string> kv; - - explicit Options(std::string str = "") { - std::string k,v, *curr = &k; - for (auto c : str) { - switch(c) { - case ',': kv[k] = v; - curr = &(k = ""); - break; - case '=': curr = &(v = ""); - break; - default: *curr += c; - } - } - kv[k] = v; - } - - std::string lookup(std::string k, std::string fallback = "") { - for (auto it = kv.find(k); it != kv.end(); ) { - return it->second; - } - return fallback; - } -}; - -template <typename T> -static std::unique_ptr<T> move_unique(T& v) { - return std::unique_ptr<T>{new T{std::move(v)}}; -} - -struct GMStream : Stream { - const skiagm::GMRegistry* registry = skiagm::GMRegistry::Head(); - - static std::unique_ptr<Stream> Create(Options) { - GMStream stream; - return move_unique(stream); - } - - struct GMSrc : Src { - skiagm::GM* (*factory)(void*); - std::unique_ptr<skiagm::GM> gm; - - std::string name() override { - gm.reset(factory(nullptr)); - return gm->getName(); - } - - SkISize size() override { - return gm->getISize(); - } - - void draw(SkCanvas* canvas) override { - canvas->clear(0xffffffff); - canvas->concat(gm->getInitialTransform()); - gm->draw(canvas); - } - }; - - std::unique_ptr<Src> next() override { - if (!registry) { - return nullptr; - } - GMSrc src; - src.factory = registry->factory(); - registry = registry->next(); - return move_unique(src); - } -}; - -struct SKPStream : Stream { - std::string dir; - std::vector<std::string> skps; - - static std::unique_ptr<Stream> Create(Options options) { - SKPStream stream; - stream.dir = options.lookup("dir", "skps"); - SkOSFile::Iter it{stream.dir.c_str(), ".skp"}; - for (SkString path; it.next(&path); ) { - stream.skps.push_back(path.c_str()); - } - return move_unique(stream); - } - - struct SKPSrc : Src { - std::string dir, path; - sk_sp<SkPicture> pic; - - std::string name() override { - return path; - } - - SkISize size() override { - auto skp = SkData::MakeFromFileName((dir+"/"+path).c_str()); - pic = SkPicture::MakeFromData(skp.get()); - return pic->cullRect().roundOut().size(); - } - - void draw(SkCanvas* canvas) override { - canvas->clear(0xffffffff); - pic->playback(canvas); - } - }; - - std::unique_ptr<Src> next() override { - if (skps.empty()) { - return nullptr; - } - SKPSrc src; - src.dir = dir; - src.path = skps.back(); - skps.pop_back(); - return move_unique(src); - } -}; - -struct Dst { - virtual ~Dst() {} - virtual SkCanvas* canvas() = 0; - virtual void write(std::string path_prefix) = 0; -}; - -struct SWDst : Dst { - sk_sp<SkSurface> surface; - - static std::unique_ptr<Dst> Create(SkISize size, Options options) { - SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); - if (options.lookup("ct") == "565") { info = info.makeColorType(kRGB_565_SkColorType); } - if (options.lookup("ct") == "f16") { info = info.makeColorType(kRGBA_F16_SkColorType); } - SWDst dst; - dst.surface = SkSurface::MakeRaster(info); - return move_unique(dst); - } - - SkCanvas* canvas() override { - return surface->getCanvas(); - } - - void write(std::string path_prefix) override { - auto image = surface->makeImageSnapshot(); - sk_sp<SkData> png{image->encode()}; - SkFILEWStream{(path_prefix + ".png").c_str()}.write(png->data(), png->size()); - } -}; - -struct { +struct StreamType { const char* name; std::unique_ptr<Stream> (*factory)(Options); -} streams[] = { - {"gm", GMStream::Create }, - {"skp", SKPStream::Create }, }; +static std::vector<StreamType> stream_types; -struct { +struct DstType { const char* name; std::unique_ptr<Dst> (*factory)(SkISize, Options); -} dsts[] = { - {"sw", SWDst::Create }, }; - +static std::vector<DstType> dst_types; int main(int argc, char** argv) { SkGraphics::Init(); @@ -343,23 +176,22 @@ int main(int argc, char** argv) { std::regex search {".*"}; std::string write_dir {""}; - std::unique_ptr<Stream> stream; - std::unique_ptr<Dst> (*dst_factory)(SkISize, Options) = nullptr; - Options dst_options; + std::unique_ptr<Stream> stream; + std::function<std::unique_ptr<Dst> (SkISize)> dst_factory; auto help = [&] { - std::string stream_types, dst_types; - for (auto s : streams) { - if (!stream_types.empty()) { - stream_types += ", "; + std::string stream_names, dst_names; + for (auto s : stream_types) { + if (!stream_names.empty()) { + stream_names += ", "; } - stream_types += s.name; + stream_names += s.name; } - for (auto d : dsts) { - if (!dst_types.empty()) { - dst_types += ", "; + for (auto d : dst_types) { + if (!dst_names.empty()) { + dst_names += ", "; } - dst_types += d.name; + dst_names += d.name; } printf("%s [-j N] [-m regex] [-s regex] [-w dir] [-h] src[:k=v,...] dst[:k=v,...] \n" @@ -374,7 +206,7 @@ int main(int argc, char** argv) { " src: content to draw: %s \n" " dst: how to draw that content: %s \n" " Some srcs and dsts have options, e.g. skp:dir=skps sw:ct=565 \n", - argv[0], stream_types.c_str(), dst_types.c_str()); + argv[0], stream_names.c_str(), dst_names.c_str()); return 1; }; @@ -385,7 +217,7 @@ int main(int argc, char** argv) { if (0 == strcmp("-w", argv[i])) { write_dir = argv[++i] ; } if (0 == strcmp("-h", argv[i])) { return help(); } - for (auto s : streams) { + for (auto s : stream_types) { size_t len = strlen(s.name); if (0 == strncmp(s.name, argv[i], len)) { switch (argv[i][len]) { @@ -394,13 +226,14 @@ int main(int argc, char** argv) { } } } - for (auto d : dsts) { + for (auto d : dst_types) { size_t len = strlen(d.name); if (0 == strncmp(d.name, argv[i], len)) { switch (argv[i][len]) { case ':': len++; - case '\0': dst_factory = d.factory; - dst_options = Options{argv[i]+len}; + case '\0': dst_factory = [=](SkISize size){ + return d.factory(size, Options{argv[i]+len}); + }; } } } @@ -463,7 +296,7 @@ int main(int argc, char** argv) { return Status::Skipped; } - auto dst = dst_factory(src->size(), dst_options); + auto dst = dst_factory(src->size()); auto canvas = dst->canvas(); src->draw(canvas); @@ -483,3 +316,33 @@ int main(int argc, char** argv) { printf("\n"); return (failed || crashed) ? 1 : 0; } + + +Register::Register(const char* name, std::unique_ptr<Stream> (*factory)(Options)) { + stream_types.push_back(StreamType{name, factory}); +} +Register::Register(const char* name, std::unique_ptr<Dst> (*factory)(SkISize, Options)) { + dst_types.push_back(DstType{name, factory}); +} + +Options::Options(std::string str) { + std::string k,v, *curr = &k; + for (auto c : str) { + switch(c) { + case ',': this->kv[k] = v; + curr = &(k = ""); + break; + case '=': curr = &(v = ""); + break; + default: *curr += c; + } + } + this->kv[k] = v; +} + +std::string Options::operator()(std::string k, std::string fallback) const { + for (auto it = kv.find(k); it != kv.end(); ) { + return it->second; + } + return fallback; +} diff --git a/tools/ok.h b/tools/ok.h new file mode 100644 index 0000000000..ab05074aac --- /dev/null +++ b/tools/ok.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef ok_DEFINED +#define ok_DEFINED + +#include "SkCanvas.h" +#include <functional> +#include <map> +#include <memory> +#include <string> + +// Not really ok-specific, but just kind of generally handy. +template <typename T> +static std::unique_ptr<T> move_unique(T& v) { + return std::unique_ptr<T>{new T{std::move(v)}}; +} + +struct Src { + virtual ~Src() {} + virtual std::string name() = 0; // ok always calls Src methods in order: + virtual SkISize size() = 0; // name() -> size() -> draw(), possibly + virtual void draw(SkCanvas*) = 0; // stopping after calling name(). +}; + +struct Stream { + virtual ~Stream() {} + virtual std::unique_ptr<Src> next() = 0; +}; + +struct Dst { + virtual ~Dst() {} + virtual SkCanvas* canvas() = 0; + virtual void write(std::string path_prefix) = 0; // All but the file extension. +}; + +class Options { + std::map<std::string, std::string> kv; +public: + explicit Options(std::string str = ""); + std::string operator()(std::string k, std::string fallback = "") const; +}; + +// Create globals to register your new type of Stream or Dst. +struct Register { + Register(const char* name, std::unique_ptr<Stream> (*factory)(Options)); + Register(const char* name, std::unique_ptr<Dst> (*factory)(SkISize, Options)); +}; + +#endif//ok_DEFINED diff --git a/tools/ok_dsts.cpp b/tools/ok_dsts.cpp new file mode 100644 index 0000000000..143650c4d4 --- /dev/null +++ b/tools/ok_dsts.cpp @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "ok.h" +#include "SkSurface.h" + +struct SWDst : Dst { + sk_sp<SkSurface> surface; + + static std::unique_ptr<Dst> Create(SkISize size, Options options) { + SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); + if (options("ct") == "565") { info = info.makeColorType(kRGB_565_SkColorType); } + if (options("ct") == "f16") { info = info.makeColorType(kRGBA_F16_SkColorType); } + SWDst dst; + dst.surface = SkSurface::MakeRaster(info); + return move_unique(dst); + } + + SkCanvas* canvas() override { + return surface->getCanvas(); + } + + void write(std::string path_prefix) override { + auto image = surface->makeImageSnapshot(); + sk_sp<SkData> png{image->encode()}; + SkFILEWStream{(path_prefix + ".png").c_str()}.write(png->data(), png->size()); + } +}; +static Register sw{"sw", SWDst::Create}; diff --git a/tools/ok_srcs.cpp b/tools/ok_srcs.cpp new file mode 100644 index 0000000000..ce3e653d92 --- /dev/null +++ b/tools/ok_srcs.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "ok.h" +#include "gm.h" +#include "SkOSFile.h" +#include "SkPicture.h" +#include <vector> + +struct GMStream : Stream { + const skiagm::GMRegistry* registry = skiagm::GMRegistry::Head(); + + static std::unique_ptr<Stream> Create(Options) { + GMStream stream; + return move_unique(stream); + } + + struct GMSrc : Src { + skiagm::GM* (*factory)(void*); + std::unique_ptr<skiagm::GM> gm; + + std::string name() override { + gm.reset(factory(nullptr)); + return gm->getName(); + } + + SkISize size() override { + return gm->getISize(); + } + + void draw(SkCanvas* canvas) override { + canvas->clear(0xffffffff); + canvas->concat(gm->getInitialTransform()); + gm->draw(canvas); + } + }; + + std::unique_ptr<Src> next() override { + if (!registry) { + return nullptr; + } + GMSrc src; + src.factory = registry->factory(); + registry = registry->next(); + return move_unique(src); + } +}; +static Register gm{"gm", GMStream::Create}; + +struct SKPStream : Stream { + std::string dir; + std::vector<std::string> skps; + + static std::unique_ptr<Stream> Create(Options options) { + SKPStream stream; + stream.dir = options("dir", "skps"); + SkOSFile::Iter it{stream.dir.c_str(), ".skp"}; + for (SkString path; it.next(&path); ) { + stream.skps.push_back(path.c_str()); + } + return move_unique(stream); + } + + struct SKPSrc : Src { + std::string dir, path; + sk_sp<SkPicture> pic; + + std::string name() override { + return path; + } + + SkISize size() override { + auto skp = SkData::MakeFromFileName((dir+"/"+path).c_str()); + pic = SkPicture::MakeFromData(skp.get()); + return pic->cullRect().roundOut().size(); + } + + void draw(SkCanvas* canvas) override { + canvas->clear(0xffffffff); + pic->playback(canvas); + } + }; + + std::unique_ptr<Src> next() override { + if (skps.empty()) { + return nullptr; + } + SKPSrc src; + src.dir = dir; + src.path = skps.back(); + skps.pop_back(); + return move_unique(src); + } +}; +static Register skp{"skp", SKPStream::Create}; |