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