aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkRecordOpts.cpp54
-rw-r--r--src/core/SkRecordPattern.h109
-rw-r--r--tests/RecordPatternTest.cpp20
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);