From d3d377f1d6f2b4450ca34a3c1b9de880b8a0632c Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Fri, 7 Dec 2012 20:56:13 +0000 Subject: [PATCH] Update filter tool to write out paths to .cpp file https://codereview.appspot.com/6843125/ git-svn-id: http://skia.googlecode.com/svn/trunk@6714 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gyp/tools.gyp | 2 + tools/filtermain.cpp | 72 ++++++++++++++++++++--- tools/path_utils.cpp | 134 +++++++++++++++++++++++++++++++++++++++++++ tools/path_utils.h | 47 +++++++++++++++ 4 files changed, 246 insertions(+), 9 deletions(-) create mode 100644 tools/path_utils.cpp create mode 100644 tools/path_utils.h diff --git a/gyp/tools.gyp b/gyp/tools.gyp index 8a31eaa817..0cdb3197a0 100644 --- a/gyp/tools.gyp +++ b/gyp/tools.gyp @@ -199,6 +199,8 @@ ], 'sources': [ '../tools/filtermain.cpp', + '../tools/path_utils.cpp', + '../tools/path_utils.h', ], 'dependencies': [ 'skia_base_libs.gyp:skia_base_libs', diff --git a/tools/filtermain.cpp b/tools/filtermain.cpp index 5dbdc22f62..28020cd02a 100644 --- a/tools/filtermain.cpp +++ b/tools/filtermain.cpp @@ -15,14 +15,16 @@ #include "SkPictureRecord.h" #include "SkStream.h" #include "picture_utils.h" +#include "path_utils.h" static void usage() { - SkDebugf("Usage: filter -i inFile [-o outFile] [-t textureDir] [-h|--help]"); - SkDebugf("\n\n"); + SkDebugf("Usage: filter -i inFile [-o outFile] [--input-dir path] [--output-dir path]\n"); + SkDebugf(" [-p pathFile] [-t textureDir] [-h|--help]\n\n"); SkDebugf(" -i inFile : file to file.\n"); SkDebugf(" -o outFile : result of filtering.\n"); SkDebugf(" --input-dir : process all files in dir with .skp extension.\n"); SkDebugf(" --output-dir : results of filtering the input dir.\n"); + SkDebugf(" -p pathFile : file in which to place compileable path data.\n"); SkDebugf(" -t textureDir : directory in which to place textures. (only available w/ single file)\n"); SkDebugf(" -h|--help : Show this help message.\n"); } @@ -30,12 +32,30 @@ static void usage() { // SkFilterRecord allows the filter to manipulate the read in SkPicture class SkFilterRecord : public SkPictureRecord { public: - SkFilterRecord(uint32_t recordFlags, SkDevice* device) + SkFilterRecord(uint32_t recordFlags, SkDevice* device, SkFILEWStream* pathStream) : INHERITED(recordFlags, device) , fTransSkipped(0) , fTransTot(0) , fScalesSkipped(0) - , fScalesTot(0) { + , fScalesTot(0) + , fPathStream(pathStream) { + } + + virtual ~SkFilterRecord() { + } + + virtual bool clipPath(const SkPath& path, SkRegion::Op op, bool doAntiAlias) SK_OVERRIDE { + if (!path.isRect(NULL) && 4 < path.countPoints()) { + sk_tools::dump_path(fPathStream, path); + } + return INHERITED::clipPath(path, op, doAntiAlias); + } + + virtual void drawPath(const SkPath& path, const SkPaint& p) SK_OVERRIDE { + if (!path.isRect(NULL) && 4 < path.countPoints()) { + sk_tools::dump_path(fPathStream, path); + } + INHERITED::drawPath(path, p); } virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE { @@ -97,6 +117,7 @@ protected: int fScalesSkipped; int fScalesTot; + SkFILEWStream* fPathStream; private: typedef SkPictureRecord INHERITED; }; @@ -119,7 +140,8 @@ static bool PNGEncodeBitmapToStream(SkWStream* stream, const SkBitmap& bitmap) { return SkImageEncoder::EncodeStream(stream, bitmap, SkImageEncoder::kPNG_Type, 100); } -int filter_picture(const SkString& inFile, const SkString& outFile, const SkString& textureDir) { +int filter_picture(const SkString& inFile, const SkString& outFile, + const SkString& textureDir, SkFILEWStream *pathStream) { SkPicture* inPicture = NULL; SkFILEStream inStream(inFile.c_str()); @@ -136,7 +158,7 @@ int filter_picture(const SkString& inFile, const SkString& outFile, const SkStri bm.setConfig(SkBitmap::kNo_Config, inPicture->width(), inPicture->height()); SkAutoTUnref dev(SkNEW_ARGS(SkDevice, (bm))); - SkAutoTUnref filterRecord(SkNEW_ARGS(SkFilterRecord, (0, dev))); + SkAutoTUnref filterRecord(SkNEW_ARGS(SkFilterRecord, (0, dev, pathStream))); // Playback the read in picture to the SkFilterRecorder to allow filtering filterRecord->beginRecording(); @@ -169,7 +191,7 @@ int tool_main(int argc, char** argv) { return -1; } - SkString inFile, outFile, inDir, outDir, textureDir; + SkString inFile, outFile, inDir, outDir, textureDir, pathFile; char* const* stop = argv + argc; for (++argv; argv < stop; ++argv) { @@ -209,6 +231,15 @@ int tool_main(int argc, char** argv) { usage(); return -1; } + } else if (strcmp(*argv, "-p") == 0) { + argv++; + if (argv < stop && **argv) { + pathFile.set(*argv); + } else { + SkDebugf("missing arg for -p\n"); + usage(); + return -1; + } } else if (strcmp(*argv, "-t") == 0) { argv++; if (argv < stop && **argv) { @@ -234,6 +265,19 @@ int tool_main(int argc, char** argv) { return -1; } + SkFILEWStream *pathStream = NULL; + + if (!pathFile.isEmpty()) { + pathStream = new SkFILEWStream(pathFile.c_str()); + if (!pathStream->isValid()) { + SkDebugf("Could open path file %s\n", pathFile.c_str()); + delete pathStream; + return -1; + } + + sk_tools::dump_path_prefix(pathStream); + } + SkOSFile::Iter iter(inDir.c_str(), "skp"); int failures = 0; SkString inputFilename, outputFilename; @@ -245,16 +289,26 @@ int tool_main(int argc, char** argv) { sk_tools::make_filepath(&outFile, outDir, inputFilename); } SkDebugf("Executing %s\n", inputFilename.c_str()); - filter_picture(inFile, outFile, textureDir); + filter_picture(inFile, outFile, textureDir, pathStream); } while(iter.next(&inputFilename)); } else if (!inFile.isEmpty()) { - filter_picture(inFile, outFile, textureDir); + filter_picture(inFile, outFile, textureDir, pathStream); } else { usage(); + if (NULL != pathStream) { + delete pathStream; + pathStream = NULL; + } return -1; } + if (NULL != pathStream) { + sk_tools::dump_path_suffix(pathStream); + delete pathStream; + pathStream = NULL; + } + SkGraphics::Term(); return 0; } diff --git a/tools/path_utils.cpp b/tools/path_utils.cpp new file mode 100644 index 0000000000..217554d1ce --- /dev/null +++ b/tools/path_utils.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "path_utils.h" +#include "SkPath.h" +#include "SkStream.h" + +namespace sk_tools { + static int gCurPathID = 0; + + void dump_path_prefix(SkFILEWStream* pathStream) { + if (NULL == pathStream) { + return; + } + + pathStream->writeText("#include \"SkScalar.h\"\n"); + pathStream->writeText("#include \"SkPoint.h\"\n"); + pathStream->writeText("#include \"SkBitmap.h\"\n"); + pathStream->writeText("#include \"SkDevice.h\"\n"); + pathStream->writeText("#include \"SkString.h\"\n"); + pathStream->writeText("#include \"SkImageEncoder.h\"\n"); + } + + void dump_path(SkFILEWStream* pathStream, const SkPath& path) { + if (NULL == pathStream) { + return; + } + + static const int kMaxPts = 200; + static const int kMaxVerbs = 200; + + int numPts = path.countPoints(); + int numVerbs = path.countVerbs(); + + SkASSERT(numPts <= kMaxPts); + SkASSERT(numVerbs <= kMaxVerbs); + + SkPoint pts[kMaxPts]; + uint8_t verbs[kMaxVerbs]; + + path.getPoints(pts, kMaxPts); + path.getVerbs(verbs, kMaxVerbs); + + const char* gStrs[] = { + "kMove_Verb", + "kLine_Verb", + "kQuad_Verb", + "kCubic_Verb", + "kClose_Verb", + "kDone_Verb" + }; + + pathStream->writeText("static const int numPts"); + pathStream->writeDecAsText(gCurPathID); + pathStream->writeText(" = "); + pathStream->writeDecAsText(numPts); + pathStream->writeText(";\n"); + + pathStream->writeText("SkPoint pts"); + pathStream->writeDecAsText(gCurPathID); + pathStream->writeText("[] = {\n"); + + for (int i = 0; i < numPts; ++i) { + SkString temp; + + pathStream->writeText(" { "); + temp.appendScalar(pts[i].fX); + temp.append("f, "); + temp.appendScalar(pts[i].fY); + temp.append("f },\n"); + pathStream->writeText(temp.c_str()); + } + pathStream->writeText("};\n"); + + pathStream->writeText("static const int numVerbs"); + pathStream->writeDecAsText(gCurPathID); + pathStream->writeText(" = "); + pathStream->writeDecAsText(numVerbs); + pathStream->writeText(";\n"); + + pathStream->writeText("uint8_t verbs"); + pathStream->writeDecAsText(gCurPathID); + pathStream->writeText("[] = {\n"); + + for (int i = 0; i < numVerbs; ++i) { + pathStream->writeText("\tSkPath::"); + pathStream->writeText(gStrs[verbs[i]]); + pathStream->writeText(",\n"); + } + pathStream->writeText("};\n"); + + gCurPathID++; + } + + void dump_path_suffix(SkFILEWStream* pathStream) { + if (NULL == pathStream) { + return; + } + + pathStream->writeText("int numPaths = "); + pathStream->writeDecAsText(gCurPathID); + pathStream->writeText(";\n"); + + pathStream->writeText("int sizes[] = {\n"); + for (int i = 0; i < gCurPathID; ++i) { + pathStream->writeText("\t numPts"); + pathStream->writeDecAsText(i); + pathStream->writeText(", numVerbs"); + pathStream->writeDecAsText(i); + pathStream->writeText(",\n"); + } + pathStream->writeText("};\n"); + + pathStream->writeText("const SkPoint* points[] = {\n"); + for (int i = 0; i < gCurPathID; ++i) { + pathStream->writeText("\tpts"); + pathStream->writeDecAsText(i); + pathStream->writeText(",\n"); + } + pathStream->writeText("};\n"); + + pathStream->writeText("const uint8_t* verbs[] = {\n"); + for (int i = 0; i < gCurPathID; ++i) { + pathStream->writeText("\t(const uint8_t*)verbs"); + pathStream->writeDecAsText(i); + pathStream->writeText(",\n"); + } + pathStream->writeText("};\n"); + } +} diff --git a/tools/path_utils.h b/tools/path_utils.h new file mode 100644 index 0000000000..d459611204 --- /dev/null +++ b/tools/path_utils.h @@ -0,0 +1,47 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef path_utils_DEFINED +#define path_utils_DEFINED + +class SkFILEWStream; +class SkPath; + +namespace sk_tools { + // These utilities help write paths to a .cpp file in a compileable form. + // To use call them in the order: + // dump_path_prefix - once per program invocation + // dump_path - once for each path of interest + // dump_path_suffix - once per program invocation + // + // The output system relies on a global current path ID and assumes that + // only one set of aggregation arrays will be written per program + // invocation. These utilities are not thread safe. + + // Write of the headers needed to compile the resulting .cpp file + void dump_path_prefix(SkFILEWStream* pathStream); + + // Write out a single path in the form: + // static const int numPts# = ...; + // SkPoint pts#[] = { ... }; + // static const int numVerbs# = ...; + // uint8_t verbs#[] = { ... }; + // Where # is a globally unique identifier + void dump_path(SkFILEWStream* pathStream, const SkPath& path); + + // Write out structures to aggregate info about the written paths: + // int numPaths = ...; + // int sizes[] = { + // numPts#, numVerbs#, + // ... + // }; + // const SkPoint* points[] = { pts#, ... }; + // const uint8_t* verbs[] = { verbs#, ... }; + void dump_path_suffix(SkFILEWStream* pathStream); +} + +#endif \ No newline at end of file -- 2.34.1