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 10 11 #include <stdio.h> 12 13 #include "SkBitmap.h" 14 #include "SkPoint.h" 15 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 20 #define MAX_TRACKING_POINTS 100 21 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 * 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 * 39 */ 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 50 // Clears all the points, but preserves the break mode. 51 void clearPoints() { 52 fCntExpectedTouched = 0; 53 fCntExpectedUntouched = 0; 54 } 55 56 // Enable the breackpoints. 57 void enableTracking(bool b) { 58 fEnabled = b; 59 } 60 61 // Returns true if breackpoints are enabled. 62 bool trackingEnabled() { 63 return fEnabled; 64 } 65 66 // Puts the tracker in Any mode. 67 void any() { 68 fBreakOnAny = true; 69 } 70 71 // Puts the tracker in Any mode. 72 void all() { 73 fBreakOnAny = false; 74 } 75 76 // returns true in in All mode. False for Any mode. 77 bool requireAllExpectedTouched() { 78 return !fBreakOnAny; 79 } 80 81 // Returns the numbers of points in which if touched, would trigger a breackpoint. 82 int cntExpectedTouched() { 83 return fCntExpectedTouched; 84 } 85 86 // Returns the points which if touched, would trigger a breackpoint. 87 // the Tracker owns the array 88 const SkIPoint* expectedTouched() { 89 return fExpectedTouched; 90 } 91 92 // Returns the numbers of points in which if touched, would disable a breackpoint. 93 int cntExpectedUntouched() { 94 return fCntExpectedUntouched; 95 } 96 97 // Returns the points which if touched, would disable a breackpoint. 98 // the Tracker owns the array 99 const SkIPoint* expectedUntouched() { 100 return fExpectedUntouched; 101 } 102 103 // Adds a point which if changes in a drawFoo operation, would trigger a breakpoint. 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 116 // Adds a point which if changes in a drawFoo operation, would disable a breakpoint. 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 129 // Starts a new rendering session - reset the number of hits. 130 void newFrame() { 131 fHits = 0; 132 } 133 134 // returns the number of breackpoints issues in this rendering session. 135 int hits() { 136 return fHits; 137 } 138 139 // Called before drawFoo to store the state of the pixels 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++) { 149 fBeforeUntouched[i] = pickColor(bitmap, fExpectedUntouched[i].x(), 150 fExpectedUntouched[i].y()); 151 } 152 } 153 154 // Called after drawFoo to evaluate what pixels have changed, it could issue a breakpoint. 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++) { 165 doBreak = doBreak || fBeforeTouched[i] != pickColor(bitmap, fExpectedTouched[i].x(), 166 fExpectedTouched[i].y()); 167 } 168 } else { 169 doBreak = true; 170 for (int i = 0 ; i < fCntExpectedTouched; i++) { 171 doBreak = doBreak && fBeforeTouched[i] != pickColor(bitmap, fExpectedTouched[i].x(), 172 fExpectedTouched[i].y()); 173 } 174 } 175 176 for (int i = 0 ; i < fCntExpectedUntouched; i++) { 177 doBreak = doBreak && fBeforeUntouched[i] == pickColor(bitmap, fExpectedUntouched[i].x(), 178 fExpectedUntouched[i].y()); 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 227 #endif // SkTracker_DEFINED 228