edisonn@google.com | cf2cfa1 | 2013-08-21 16:31:37 +0000 | [diff] [blame] | 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 | #ifndef SkTracker_DEFINED |
| 9 | #define SkTracker_DEFINED |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 10 | |
| 11 | #include "SkBitmap.h" |
| 12 | #include "SkPoint.h" |
| 13 | |
edisonn@google.com | e50d9a1 | 2013-10-10 20:58:22 +0000 | [diff] [blame] | 14 | // TODO(edisonn): draw plan from point! - list of draw ops of a point, like a tree! |
| 15 | // TODO(edisonn): Minimal PDF to draw some points - remove everything that it is not needed, |
| 16 | // save pdf uncompressed |
| 17 | |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 18 | #define MAX_TRACKING_POINTS 100 |
| 19 | |
edisonn@google.com | 2af2ad9 | 2013-10-11 16:17:44 +0000 | [diff] [blame] | 20 | /** \class SkTracker |
| 21 | * |
| 22 | * A Tracker can be attached to a SkTrackDevice and it will store the track pixels. |
| 23 | * It can be used with SampleApp to investigate bugs (CL not checked in yet). |
| 24 | * |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 25 | * The Tracker tracks 2 sets of points |
| 26 | * A) one which is expected to issue breackpoints if the pixels are changes |
| 27 | * B) one which if changes will disable the breackpoint |
| 28 | * For point in A) there are two modes: |
| 29 | * A.1) a breackpoint require that any of the points is changed |
| 30 | * A.2) a breackpoint require that all of the points is changed |
| 31 | * Points in B are allways in "any mode" - chaning the value of any pixel, will disable |
| 32 | * the breackpoint |
| 33 | * |
| 34 | * Point in A) are used to show what are the areas of interest, while poit in B are used to |
| 35 | * disable breackpoints which would be issued in background change. |
| 36 | * |
edisonn@google.com | 2af2ad9 | 2013-10-11 16:17:44 +0000 | [diff] [blame] | 37 | */ |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 38 | class SkTracker { |
| 39 | public: |
| 40 | SkTracker() : fEnabled(false) |
| 41 | , fBreakOnAny(false) |
| 42 | , fCntExpectedTouched(0) |
| 43 | , fCntExpectedUntouched(0) |
| 44 | , fHits(0) {} |
| 45 | |
| 46 | virtual ~SkTracker() {} |
| 47 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 48 | // Clears all the points, but preserves the break mode. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 49 | void clearPoints() { |
| 50 | fCntExpectedTouched = 0; |
| 51 | fCntExpectedUntouched = 0; |
| 52 | } |
| 53 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 54 | // Enable the breackpoints. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 55 | void enableTracking(bool b) { |
| 56 | fEnabled = b; |
| 57 | } |
| 58 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 59 | // Returns true if breackpoints are enabled. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 60 | bool trackingEnabled() { |
| 61 | return fEnabled; |
| 62 | } |
| 63 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 64 | // Puts the tracker in Any mode. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 65 | void any() { |
| 66 | fBreakOnAny = true; |
| 67 | } |
| 68 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 69 | // Puts the tracker in Any mode. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 70 | void all() { |
| 71 | fBreakOnAny = false; |
| 72 | } |
| 73 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 74 | // returns true in in All mode. False for Any mode. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 75 | bool requireAllExpectedTouched() { |
| 76 | return !fBreakOnAny; |
| 77 | } |
| 78 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 79 | // Returns the numbers of points in which if touched, would trigger a breackpoint. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 80 | int cntExpectedTouched() { |
| 81 | return fCntExpectedTouched; |
| 82 | } |
| 83 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 84 | // Returns the points which if touched, would trigger a breackpoint. |
| 85 | // the Tracker owns the array |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 86 | const SkIPoint* expectedTouched() { |
| 87 | return fExpectedTouched; |
| 88 | } |
| 89 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 90 | // Returns the numbers of points in which if touched, would disable a breackpoint. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 91 | int cntExpectedUntouched() { |
| 92 | return fCntExpectedUntouched; |
| 93 | } |
| 94 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 95 | // Returns the points which if touched, would disable a breackpoint. |
| 96 | // the Tracker owns the array |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 97 | const SkIPoint* expectedUntouched() { |
| 98 | return fExpectedUntouched; |
| 99 | } |
| 100 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 101 | // Adds a point which if changes in a drawFoo operation, would trigger a breakpoint. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 102 | bool addExpectTouch(int x, int y) { |
| 103 | if (fCntExpectedTouched >= MAX_TRACKING_POINTS) { |
| 104 | return false; |
| 105 | } |
| 106 | if (found(x, y)) { |
| 107 | return false; |
| 108 | } |
| 109 | fExpectedTouched[fCntExpectedTouched] = SkIPoint::Make(x, y); |
| 110 | fCntExpectedTouched++; |
| 111 | return true; |
| 112 | } |
| 113 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 114 | // Adds a point which if changes in a drawFoo operation, would disable a breakpoint. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 115 | bool addExpectUntouch(int x, int y) { |
| 116 | if (fCntExpectedUntouched >= MAX_TRACKING_POINTS) { |
| 117 | return false; |
| 118 | } |
| 119 | if (found(x, y)) { |
| 120 | return false; |
| 121 | } |
| 122 | fExpectedUntouched[fCntExpectedUntouched] = SkIPoint::Make(x, y); |
| 123 | fCntExpectedUntouched++; |
| 124 | return true; |
| 125 | } |
| 126 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 127 | // Starts a new rendering session - reset the number of hits. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 128 | void newFrame() { |
| 129 | fHits = 0; |
| 130 | } |
| 131 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 132 | // returns the number of breackpoints issues in this rendering session. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 133 | int hits() { |
| 134 | return fHits; |
| 135 | } |
| 136 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 137 | // Called before drawFoo to store the state of the pixels |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 138 | void before(const SkBitmap& bitmap) { |
| 139 | if (fCntExpectedTouched == 0) { |
| 140 | return; |
| 141 | } |
| 142 | |
| 143 | for (int i = 0 ; i < fCntExpectedTouched; i++) { |
| 144 | fBeforeTouched[i] = pickColor(bitmap, fExpectedTouched[i].x(), fExpectedTouched[i].y()); |
| 145 | } |
| 146 | for (int i = 0 ; i < fCntExpectedUntouched; i++) { |
edisonn@google.com | e50d9a1 | 2013-10-10 20:58:22 +0000 | [diff] [blame] | 147 | fBeforeUntouched[i] = pickColor(bitmap, fExpectedUntouched[i].x(), |
| 148 | fExpectedUntouched[i].y()); |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 149 | } |
| 150 | } |
| 151 | |
edisonn@google.com | d03c2c7 | 2013-10-11 18:26:45 +0000 | [diff] [blame] | 152 | // Called after drawFoo to evaluate what pixels have changed, it could issue a breakpoint. |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 153 | // any/all of the expected touched has to be changed, and all expected untouched must be intact |
| 154 | void after(const SkBitmap& bitmap) { |
| 155 | if (fCntExpectedTouched == 0) { |
| 156 | return; |
| 157 | } |
| 158 | |
| 159 | bool doBreak; |
| 160 | if (fBreakOnAny) { |
| 161 | doBreak = false; |
| 162 | for (int i = 0 ; i < fCntExpectedTouched; i++) { |
edisonn@google.com | e50d9a1 | 2013-10-10 20:58:22 +0000 | [diff] [blame] | 163 | doBreak = doBreak || fBeforeTouched[i] != pickColor(bitmap, fExpectedTouched[i].x(), |
| 164 | fExpectedTouched[i].y()); |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 165 | } |
| 166 | } else { |
| 167 | doBreak = true; |
| 168 | for (int i = 0 ; i < fCntExpectedTouched; i++) { |
edisonn@google.com | e50d9a1 | 2013-10-10 20:58:22 +0000 | [diff] [blame] | 169 | doBreak = doBreak && fBeforeTouched[i] != pickColor(bitmap, fExpectedTouched[i].x(), |
| 170 | fExpectedTouched[i].y()); |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 171 | } |
| 172 | } |
| 173 | |
| 174 | for (int i = 0 ; i < fCntExpectedUntouched; i++) { |
edisonn@google.com | e50d9a1 | 2013-10-10 20:58:22 +0000 | [diff] [blame] | 175 | doBreak = doBreak && fBeforeUntouched[i] == pickColor(bitmap, fExpectedUntouched[i].x(), |
| 176 | fExpectedUntouched[i].y()); |
edisonn@google.com | ac03d91 | 2013-07-22 15:36:39 +0000 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | if (doBreak) { |
| 180 | fHits++; |
| 181 | if (fEnabled) { |
| 182 | breakExecution(); |
| 183 | } |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | private: |
| 188 | inline SkColor pickColor(const SkBitmap& bitmap, int x, int y) { |
| 189 | return bitmap.getColor(x, y); |
| 190 | } |
| 191 | |
| 192 | void breakExecution() { |
| 193 | printf("break;\n"); |
| 194 | } |
| 195 | |
| 196 | inline bool found(int x, int y) { |
| 197 | for (int i = 0 ; i < fCntExpectedTouched; i++) { |
| 198 | if (x == fExpectedTouched[i].x() && y == fExpectedTouched[i].y()) { |
| 199 | return true; |
| 200 | } |
| 201 | } |
| 202 | for (int i = 0 ; i < fCntExpectedUntouched; i++) { |
| 203 | if (x == fExpectedUntouched[i].x() && y == fExpectedUntouched[i].y()) { |
| 204 | return true; |
| 205 | } |
| 206 | } |
| 207 | return false; |
| 208 | } |
| 209 | |
| 210 | |
| 211 | bool fEnabled; |
| 212 | // break on any change on expected touched or all. |
| 213 | bool fBreakOnAny; |
| 214 | SkIPoint fExpectedTouched[MAX_TRACKING_POINTS]; |
| 215 | SkColor fBeforeTouched[MAX_TRACKING_POINTS]; |
| 216 | int fCntExpectedTouched; |
| 217 | |
| 218 | SkIPoint fExpectedUntouched[MAX_TRACKING_POINTS]; |
| 219 | SkColor fBeforeUntouched[MAX_TRACKING_POINTS]; |
| 220 | int fCntExpectedUntouched; |
| 221 | |
| 222 | int fHits; |
| 223 | }; |
| 224 | |
edisonn@google.com | cf2cfa1 | 2013-08-21 16:31:37 +0000 | [diff] [blame] | 225 | #endif // SkTracker_DEFINED |