diff options
author | mtklein <mtklein@chromium.org> | 2015-11-19 08:53:27 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-19 08:53:27 -0800 |
commit | 24e7db8b2ea663f8fe4d7bbfa1d686fd643990bb (patch) | |
tree | 9cbb16e3fc5e4ed8df7301f92bf1bafcee07dedd | |
parent | 4222e19aeaf72ccfb61f83f4fe41010750161c74 (diff) |
Modernize SkRecordPattern.h
- Fold Or, Or3, Or4 into one flexible Or.
- Fold Pattern1...Pattern7 into one flexible Pattern.
- Rename Star Greedy
Still fighting with a flexible get<N>() method instead of first, second, third, etc.
BUG=skia:
Review URL: https://codereview.chromium.org/1465443002
-rw-r--r-- | src/core/SkRecordOpts.cpp | 54 | ||||
-rw-r--r-- | src/core/SkRecordPattern.h | 109 | ||||
-rw-r--r-- | tests/RecordPatternTest.cpp | 20 |
3 files changed, 76 insertions, 107 deletions
diff --git a/src/core/SkRecordOpts.cpp b/src/core/SkRecordOpts.cpp index 04c72c32cc..d363712f3a 100644 --- a/src/core/SkRecordOpts.cpp +++ b/src/core/SkRecordOpts.cpp @@ -27,33 +27,33 @@ void SkRecordOptimize(SkRecord* record) { } // Most of the optimizations in this file are pattern-based. These are all defined as structs with: -// - a Pattern typedef -// - a bool onMatch(SkRceord*, Pattern*, int begin, int end) method, +// - a Match typedef +// - a bool onMatch(SkRceord*, Match*, int begin, int end) method, // which returns true if it made changes and false if not. // Run a pattern-based optimization once across the SkRecord, returning true if it made any changes. -// It looks for spans which match Pass::Pattern, and when found calls onMatch() with the pattern, +// It looks for spans which match Pass::Match, and when found calls onMatch() with that pattern, // record, and [begin,end) span of the commands that matched. template <typename Pass> static bool apply(Pass* pass, SkRecord* record) { - typename Pass::Pattern pattern; + typename Pass::Match match; bool changed = false; int begin, end = 0; - while (pattern.search(record, &begin, &end)) { - changed |= pass->onMatch(record, &pattern, begin, end); + while (match.search(record, &begin, &end)) { + changed |= pass->onMatch(record, &match, begin, end); } return changed; } // Turns the logical NoOp Save and Restore in Save-Draw*-Restore patterns into actual NoOps. struct SaveOnlyDrawsRestoreNooper { - typedef Pattern3<Is<Save>, - Star<Or<Is<NoOp>, IsDraw> >, - Is<Restore> > - Pattern; + typedef Pattern<Is<Save>, + Greedy<Or<Is<NoOp>, IsDraw>>, + Is<Restore>> + Match; - bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) { + bool onMatch(SkRecord* record, Match*, int begin, int end) { record->replace<NoOp>(begin); // Save record->replace<NoOp>(end-1); // Restore return true; @@ -119,17 +119,17 @@ static bool fold_opacity_layer_color_to_paint(const SkPaint& layerPaint, // Turns logical no-op Save-[non-drawing command]*-Restore patterns into actual no-ops. struct SaveNoDrawsRestoreNooper { - // Star matches greedily, so we also have to exclude Save and Restore. + // Greedy matches greedily, so we also have to exclude Save and Restore. // Nested SaveLayers need to be excluded, or we'll match their Restore! - typedef Pattern3<Is<Save>, - Star<Not<Or4<Is<Save>, + typedef Pattern<Is<Save>, + Greedy<Not<Or<Is<Save>, Is<SaveLayer>, Is<Restore>, - IsDraw> > >, - Is<Restore> > - Pattern; + IsDraw>>>, + Is<Restore>> + Match; - bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) { + bool onMatch(SkRecord* record, Match*, int begin, int end) { // The entire span between Save and Restore (inclusively) does nothing. for (int i = begin; i < end; i++) { record->replace<NoOp>(i); @@ -148,17 +148,17 @@ void SkRecordNoopSaveRestores(SkRecord* record) { // For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's alpha into the // draw, and no-op the SaveLayer and Restore. struct SaveLayerDrawRestoreNooper { - typedef Pattern3<Is<SaveLayer>, IsDraw, Is<Restore> > Pattern; + typedef Pattern<Is<SaveLayer>, IsDraw, Is<Restore>> Match; - bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) { + bool onMatch(SkRecord* record, Match* match, int begin, int end) { // A SaveLayer's bounds field is just a hint, so we should be free to ignore it. - SkPaint* layerPaint = pattern->first<SaveLayer>()->paint; + SkPaint* layerPaint = match->first<SaveLayer>()->paint; if (nullptr == layerPaint) { // There wasn't really any point to this SaveLayer at all. return KillSaveLayerAndRestore(record, begin); } - SkPaint* drawPaint = pattern->second<SkPaint>(); + SkPaint* drawPaint = match->second<SkPaint>(); if (drawPaint == nullptr) { // We can just give the draw the SaveLayer's paint. // TODO(mtklein): figure out how to do this clearly @@ -194,11 +194,11 @@ void SkRecordNoopSaveLayerDrawRestores(SkRecord* record) { Restore */ struct SvgOpacityAndFilterLayerMergePass { - typedef Pattern7<Is<SaveLayer>, Is<Save>, Is<ClipRect>, Is<SaveLayer>, - Is<Restore>, Is<Restore>, Is<Restore> > Pattern; + typedef Pattern<Is<SaveLayer>, Is<Save>, Is<ClipRect>, Is<SaveLayer>, + Is<Restore>, Is<Restore>, Is<Restore>> Match; - bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) { - SkPaint* opacityPaint = pattern->first<SaveLayer>()->paint; + bool onMatch(SkRecord* record, Match* match, int begin, int end) { + SkPaint* opacityPaint = match->first<SaveLayer>()->paint; if (nullptr == opacityPaint) { // There wasn't really any point to this SaveLayer at all. return KillSaveLayerAndRestore(record, begin); @@ -206,7 +206,7 @@ struct SvgOpacityAndFilterLayerMergePass { // This layer typically contains a filter, but this should work for layers with for other // purposes too. - SkPaint* filterLayerPaint = pattern->fourth<SaveLayer>()->paint; + SkPaint* filterLayerPaint = match->fourth<SaveLayer>()->paint; if (filterLayerPaint == nullptr) { // We can just give the inner SaveLayer the paint of the outer SaveLayer. // TODO(mtklein): figure out how to do this clearly diff --git a/src/core/SkRecordPattern.h b/src/core/SkRecordPattern.h index d9568b360a..9493bbfaf7 100644 --- a/src/core/SkRecordPattern.h +++ b/src/core/SkRecordPattern.h @@ -80,44 +80,48 @@ struct Not { bool operator()(T* ptr) { return !Matcher()(ptr); } }; -// Matches if either of A or B does. Stores nothing. -template <typename A, typename B> +// Matches if any of First or Rest... does. Stores nothing. +template <typename First, typename... Rest> struct Or { template <typename T> - bool operator()(T* ptr) { return A()(ptr) || B()(ptr); } + bool operator()(T* ptr) { return First()(ptr) || Or<Rest...>()(ptr); } +}; +template <typename First> +struct Or<First> { + template <typename T> + bool operator()(T* ptr) { return First()(ptr); } }; -// Matches if any of A, B or C does. Stores nothing. -template <typename A, typename B, typename C> -struct Or3 : Or<A, Or<B, C> > {}; - -// Matches if any of A, B, C or D does. Stores nothing. -template <typename A, typename B, typename C, typename D> -struct Or4 : Or<A, Or<B, Or<C, D> > > {}; -// Star is a special matcher that greedily matches Matcher 0 or more times. Stores nothing. +// Greedy is a special matcher that greedily matches Matcher 0 or more times. Stores nothing. template <typename Matcher> -struct Star { +struct Greedy { template <typename T> bool operator()(T* ptr) { return Matcher()(ptr); } }; -// Cons builds a list of Matchers. -// It first matches Matcher (something from above), then Pattern (another Cons or Nil). +// Pattern matches each of its matchers in order. // // This is the main entry point to pattern matching, and so provides a couple of extra API bits: // - search scans through the record to look for matches; -// - first, second, and third return the data stored by their respective matchers in the pattern. -// -// These Cons build lists analogously to Lisp's "cons". See Pattern# for the "list" equivalent. -template <typename Matcher, typename Pattern> -class Cons { +// - first, second, third, ... return the data stored by their respective matchers in the pattern. + +template <typename... Matchers> class Pattern; + +template <> class Pattern<> { public: - // If this pattern matches the SkRecord starting at i, + // Bottoms out recursion. Just return whatever i the front decided on. + int match(SkRecord*, int i) { return i; } +}; + +template <typename First, typename... Rest> +class Pattern<First, Rest...> { +public: + // If this pattern matches the SkRecord starting from i, // return the index just past the end of the pattern, otherwise return 0. SK_ALWAYS_INLINE int match(SkRecord* record, int i) { - i = this->matchHead(&fHead, record, i); - return i == 0 ? 0 : fTail.match(record, i); + i = this->matchFirst(&fFirst, record, i); + return i > 0 ? fRest.match(record, i) : 0; } // Starting from *end, walk through the SkRecord to find the first span matching this pattern. @@ -132,31 +136,29 @@ public: return false; } - // Once either match or search has succeeded, access the stored data of the first, second, - // or third matcher in this pattern. Add as needed for longer patterns. - // T is checked statically at compile time; no casting is involved. It's just an API wart. - template <typename T> T* first() { return fHead.get(); } - template <typename T> T* second() { return fTail.fHead.get(); } - template <typename T> T* third() { return fTail.fTail.fHead.get(); } - template <typename T> T* fourth() { return fTail.fTail.fTail.fHead.get(); } + // TODO: some sort of smart get<i>() + template <typename T> T* first() { return fFirst.get(); } + template <typename T> T* second() { return fRest.template first<T>(); } + template <typename T> T* third() { return fRest.template second<T>(); } + template <typename T> T* fourth() { return fRest.template third<T>(); } private: - // If head isn't a Star, try to match at i once. + // If first isn't a Greedy, try to match at i once. template <typename T> - int matchHead(T*, SkRecord* record, int i) { + int matchFirst(T* first, SkRecord* record, int i) { if (i < record->count()) { - if (record->mutate<bool>(i, fHead)) { + if (record->mutate<bool>(i, *first)) { return i+1; } } return 0; } - // If head is a Star, walk i until it doesn't match. + // If first is a Greedy, walk i until it doesn't match. template <typename T> - int matchHead(Star<T>*, SkRecord* record, int i) { + int matchFirst(Greedy<T>* first, SkRecord* record, int i) { while (i < record->count()) { - if (!record->mutate<bool>(i, fHead)) { + if (!record->mutate<bool>(i, *first)) { return i; } i++; @@ -164,43 +166,10 @@ private: return 0; } - Matcher fHead; - Pattern fTail; - - // All Cons are friends with each other. This lets first, second, and third work. - template <typename, typename> friend class Cons; + First fFirst; + Pattern<Rest...> fRest; }; -// Nil is the end of every pattern Cons chain. -struct Nil { - // Bottoms out recursion down the fTail chain. Just return whatever i the front decided on. - int match(SkRecord*, int i) { return i; } -}; - -// These Pattern# types are syntax sugar over Cons and Nil, just to help eliminate some of the -// template noise. Use these if you can. Feel free to add more for longer patterns. -// All types A, B, C, ... are Matchers. -template <typename A> -struct Pattern1 : Cons<A, Nil> {}; - -template <typename A, typename B> -struct Pattern2 : Cons<A, Pattern1<B> > {}; - -template <typename A, typename B, typename C> -struct Pattern3 : Cons<A, Pattern2<B, C> > {}; - -template <typename A, typename B, typename C, typename D> -struct Pattern4 : Cons<A, Pattern3<B, C, D> > {}; - -template <typename A, typename B, typename C, typename D, typename E> -struct Pattern5 : Cons<A, Pattern4<B, C, D, E> > {}; - -template <typename A, typename B, typename C, typename D, typename E, typename F> -struct Pattern6 : Cons<A, Pattern5<B, C, D, E, F> > {}; - -template <typename A, typename B, typename C, typename D, typename E, typename F, typename G> -struct Pattern7 : Cons<A, Pattern6<B, C, D, E, F, G> > {}; - } // namespace SkRecords #endif//SkRecordPattern_DEFINED diff --git a/tests/RecordPatternTest.cpp b/tests/RecordPatternTest.cpp index d1e48bb838..33a0114c35 100644 --- a/tests/RecordPatternTest.cpp +++ b/tests/RecordPatternTest.cpp @@ -13,9 +13,9 @@ #include "SkRecords.h" using namespace SkRecords; -typedef Pattern3<Is<Save>, - Is<ClipRect>, - Is<Restore> > +typedef Pattern<Is<Save>, + Is<ClipRect>, + Is<Restore>> SaveClipRectRestore; DEF_TEST(RecordPattern_Simple, r) { @@ -77,8 +77,8 @@ DEF_TEST(RecordPattern_DontMatchSubsequences, r) { REPORTER_ASSERT(r, !pattern.match(&record, 0)); } -DEF_TEST(RecordPattern_Star, r) { - Pattern3<Is<Save>, Star<Is<ClipRect> >, Is<Restore> > pattern; +DEF_TEST(RecordPattern_Greedy, r) { + Pattern<Is<Save>, Greedy<Is<ClipRect>>, Is<Restore>> pattern; SkRecord record; SkRecorder recorder(&record, 1920, 1200); @@ -98,11 +98,11 @@ DEF_TEST(RecordPattern_Star, r) { } DEF_TEST(RecordPattern_Complex, r) { - Pattern3<Is<Save>, - Star<Not<Or3<Is<Save>, + Pattern<Is<Save>, + Greedy<Not<Or<Is<Save>, Is<Restore>, - IsDraw> > >, - Is<Restore> > pattern; + IsDraw>>>, + Is<Restore>> pattern; SkRecord record; SkRecorder recorder(&record, 1920, 1200); @@ -142,7 +142,7 @@ DEF_TEST(RecordPattern_Complex, r) { } DEF_TEST(RecordPattern_SaveLayerIsNotADraw, r) { - Pattern1<IsDraw> pattern; + Pattern<IsDraw> pattern; SkRecord record; SkRecorder recorder(&record, 1920, 1200); |