Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: src/core/SkCanvas.cpp

Issue 183453002: add new onClip* methods to SkCanvas (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: more cleanup Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2008 The Android Open Source Project 3 * Copyright 2008 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkCanvas.h" 10 #include "SkCanvas.h"
(...skipping 1129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 void SkCanvas::resetMatrix() { 1140 void SkCanvas::resetMatrix() {
1141 SkMatrix matrix; 1141 SkMatrix matrix;
1142 1142
1143 matrix.reset(); 1143 matrix.reset();
1144 this->setMatrix(matrix); 1144 this->setMatrix(matrix);
1145 } 1145 }
1146 1146
1147 ////////////////////////////////////////////////////////////////////////////// 1147 //////////////////////////////////////////////////////////////////////////////
1148 1148
1149 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1149 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1150 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1151 this->onClipRect(rect, op, edgeStyle);
1152 return !this->isClipEmpty();
1153 }
1154
1155 void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edg eStyle) {
1150 #ifdef SK_ENABLE_CLIP_QUICKREJECT 1156 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1151 if (SkRegion::kIntersect_Op == op) { 1157 if (SkRegion::kIntersect_Op == op) {
1152 if (fMCRec->fRasterClip->isEmpty()) { 1158 if (fMCRec->fRasterClip->isEmpty()) {
1153 return false; 1159 return false;
1154 } 1160 }
1155 1161
1156 if (this->quickReject(rect)) { 1162 if (this->quickReject(rect)) {
1157 fDeviceCMDirty = true; 1163 fDeviceCMDirty = true;
1158 fCachedLocalClipBoundsDirty = true; 1164 fCachedLocalClipBoundsDirty = true;
1159 1165
1160 fClipStack.clipEmpty(); 1166 fClipStack.clipEmpty();
1161 return fMCRec->fRasterClip->setEmpty(); 1167 return fMCRec->fRasterClip->setEmpty();
1162 } 1168 }
1163 } 1169 }
1164 #endif 1170 #endif
1165 1171
1166 AutoValidateClip avc(this); 1172 AutoValidateClip avc(this);
1167 1173
1168 fDeviceCMDirty = true; 1174 fDeviceCMDirty = true;
1169 fCachedLocalClipBoundsDirty = true; 1175 fCachedLocalClipBoundsDirty = true;
1170 doAA &= fAllowSoftClip; 1176 if (!fAllowSoftClip) {
1177 edgeStyle = kHard_ClipEdgeStyle;
1178 }
1171 1179
1172 if (fMCRec->fMatrix->rectStaysRect()) { 1180 if (fMCRec->fMatrix->rectStaysRect()) {
1173 // for these simpler matrices, we can stay a rect even after applying 1181 // for these simpler matrices, we can stay a rect even after applying
1174 // the matrix. This means we don't have to a) make a path, and b) tell 1182 // the matrix. This means we don't have to a) make a path, and b) tell
1175 // the region code to scan-convert the path, only to discover that it 1183 // the region code to scan-convert the path, only to discover that it
1176 // is really just a rect. 1184 // is really just a rect.
1177 SkRect r; 1185 SkRect r;
1178 1186
1179 fMCRec->fMatrix->mapRect(&r, rect); 1187 fMCRec->fMatrix->mapRect(&r, rect);
1180 fClipStack.clipDevRect(r, op, doAA); 1188 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1181 return fMCRec->fRasterClip->op(r, op, doAA); 1189 fMCRec->fRasterClip->op(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1182 } else { 1190 } else {
1183 // since we're rotated or some such thing, we convert the rect to a path 1191 // since we're rotated or some such thing, we convert the rect to a path
1184 // and clip against that, since it can handle any matrix. However, to 1192 // and clip against that, since it can handle any matrix. However, to
1185 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1193 // avoid recursion in the case where we are subclassed (e.g. Pictures)
1186 // we explicitly call "our" version of clipPath. 1194 // we explicitly call "our" version of clipPath.
1187 SkPath path; 1195 SkPath path;
1188 1196
1189 path.addRect(rect); 1197 path.addRect(rect);
1190 return this->SkCanvas::clipPath(path, op, doAA); 1198 this->SkCanvas::onClipPath(path, op, edgeStyle);
1191 } 1199 }
1192 } 1200 }
1193 1201
1194 static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip, 1202 static void clip_path_helper(const SkCanvas* canvas, SkRasterClip* currClip,
1195 const SkPath& devPath, SkRegion::Op op, bool doAA) { 1203 const SkPath& devPath, SkRegion::Op op, bool doAA) {
1196 // base is used to limit the size (and therefore memory allocation) of the 1204 // base is used to limit the size (and therefore memory allocation) of the
1197 // region that results from scan converting devPath. 1205 // region that results from scan converting devPath.
1198 SkRegion base; 1206 SkRegion base;
1199 1207
1200 if (SkRegion::kIntersect_Op == op) { 1208 if (SkRegion::kIntersect_Op == op) {
1201 // since we are intersect, we can do better (tighter) with currRgn's 1209 // since we are intersect, we can do better (tighter) with currRgn's
1202 // bounds, than just using the device. However, if currRgn is complex, 1210 // bounds, than just using the device. However, if currRgn is complex,
1203 // our region blitter may hork, so we do that case in two steps. 1211 // our region blitter may hork, so we do that case in two steps.
1204 if (currClip->isRect()) { 1212 if (currClip->isRect()) {
1205 // FIXME: we should also be able to do this when currClip->isBW(), 1213 // FIXME: we should also be able to do this when currClip->isBW(),
1206 // but relaxing the test above triggers GM asserts in 1214 // but relaxing the test above triggers GM asserts in
1207 // SkRgnBuilder::blitH(). We need to investigate what's going on. 1215 // SkRgnBuilder::blitH(). We need to investigate what's going on.
1208 return currClip->setPath(devPath, currClip->bwRgn(), doAA); 1216 currClip->setPath(devPath, currClip->bwRgn(), doAA);
1209 } else { 1217 } else {
1210 base.setRect(currClip->getBounds()); 1218 base.setRect(currClip->getBounds());
1211 SkRasterClip clip; 1219 SkRasterClip clip;
1212 clip.setPath(devPath, base, doAA); 1220 clip.setPath(devPath, base, doAA);
1213 return currClip->op(clip, op); 1221 currClip->op(clip, op);
1214 } 1222 }
1215 } else { 1223 } else {
1216 const SkBaseDevice* device = canvas->getDevice(); 1224 const SkBaseDevice* device = canvas->getDevice();
1217 if (!device) { 1225 if (!device) {
1218 return currClip->setEmpty(); 1226 currClip->setEmpty();
1227 return;
1219 } 1228 }
1220 1229
1221 base.setRect(0, 0, device->width(), device->height()); 1230 base.setRect(0, 0, device->width(), device->height());
1222 1231
1223 if (SkRegion::kReplace_Op == op) { 1232 if (SkRegion::kReplace_Op == op) {
1224 return currClip->setPath(devPath, base, doAA); 1233 currClip->setPath(devPath, base, doAA);
1225 } else { 1234 } else {
1226 SkRasterClip clip; 1235 SkRasterClip clip;
1227 clip.setPath(devPath, base, doAA); 1236 clip.setPath(devPath, base, doAA);
1228 return currClip->op(clip, op); 1237 currClip->op(clip, op);
1229 } 1238 }
1230 } 1239 }
1231 } 1240 }
1232 1241
1233 bool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 1242 bool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1243 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1234 if (rrect.isRect()) { 1244 if (rrect.isRect()) {
1235 // call the non-virtual version 1245 this->onClipRect(rrect.getBounds(), op, edgeStyle);
1236 return this->SkCanvas::clipRect(rrect.getBounds(), op, doAA); 1246 } else {
1247 this->onClipRRect(rrect, op, edgeStyle);
1237 } 1248 }
1249 return !this->isClipEmpty();
1250 }
1238 1251
1252 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1239 SkRRect transformedRRect; 1253 SkRRect transformedRRect;
1240 if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) { 1254 if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) {
1241 AutoValidateClip avc(this); 1255 AutoValidateClip avc(this);
1242 1256
1243 fDeviceCMDirty = true; 1257 fDeviceCMDirty = true;
1244 fCachedLocalClipBoundsDirty = true; 1258 fCachedLocalClipBoundsDirty = true;
1245 doAA &= fAllowSoftClip; 1259 if (!fAllowSoftClip) {
1260 edgeStyle = kHard_ClipEdgeStyle;
1261 }
1246 1262
1247 fClipStack.clipDevRRect(transformedRRect, op, doAA); 1263 fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edg eStyle);
1248 1264
1249 SkPath devPath; 1265 SkPath devPath;
1250 devPath.addRRect(transformedRRect); 1266 devPath.addRRect(transformedRRect);
1251 1267
1252 return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); 1268 clip_path_helper(this, fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeS tyle == edgeStyle);
1269 return;
1253 } 1270 }
1254 1271
1255 SkPath path; 1272 SkPath path;
1256 path.addRRect(rrect); 1273 path.addRRect(rrect);
1257 // call the non-virtual version 1274 // call the non-virtual version
1258 return this->SkCanvas::clipPath(path, op, doAA); 1275 this->SkCanvas::onClipPath(path, op, edgeStyle);
1259 } 1276 }
1260 1277
1261 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1278 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1279 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1280 SkRect r;
1281 if (!path.isInverseFillType() && path.isRect(&r)) {
1282 this->onClipRect(r, op, edgeStyle);
1283 } else {
1284 this->onClipPath(path, op, edgeStyle);
1285 }
1286
1287 return !this->isClipEmpty();
1288 }
1289
1290 void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edg eStyle) {
1262 #ifdef SK_ENABLE_CLIP_QUICKREJECT 1291 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1263 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1292 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1264 if (fMCRec->fRasterClip->isEmpty()) { 1293 if (fMCRec->fRasterClip->isEmpty()) {
1265 return false; 1294 return false;
1266 } 1295 }
1267 1296
1268 if (this->quickReject(path.getBounds())) { 1297 if (this->quickReject(path.getBounds())) {
1269 fDeviceCMDirty = true; 1298 fDeviceCMDirty = true;
1270 fCachedLocalClipBoundsDirty = true; 1299 fCachedLocalClipBoundsDirty = true;
1271 1300
1272 fClipStack.clipEmpty(); 1301 fClipStack.clipEmpty();
1273 return fMCRec->fRasterClip->setEmpty(); 1302 return fMCRec->fRasterClip->setEmpty();
1274 } 1303 }
1275 } 1304 }
1276 #endif 1305 #endif
1277 1306
1278 AutoValidateClip avc(this); 1307 AutoValidateClip avc(this);
1279 1308
1280 fDeviceCMDirty = true; 1309 fDeviceCMDirty = true;
1281 fCachedLocalClipBoundsDirty = true; 1310 fCachedLocalClipBoundsDirty = true;
1282 doAA &= fAllowSoftClip; 1311 if (!fAllowSoftClip) {
1312 edgeStyle = kHard_ClipEdgeStyle;
1313 }
1283 1314
1284 SkPath devPath; 1315 SkPath devPath;
1285 path.transform(*fMCRec->fMatrix, &devPath); 1316 path.transform(*fMCRec->fMatrix, &devPath);
1286 1317
1287 // Check if the transfomation, or the original path itself 1318 // Check if the transfomation, or the original path itself
1288 // made us empty. Note this can also happen if we contained NaN 1319 // made us empty. Note this can also happen if we contained NaN
1289 // values. computing the bounds detects this, and will set our 1320 // values. computing the bounds detects this, and will set our
1290 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1321 // bounds to empty if that is the case. (see SkRect::set(pts, count))
1291 if (devPath.getBounds().isEmpty()) { 1322 if (devPath.getBounds().isEmpty()) {
1292 // resetting the path will remove any NaN or other wanky values 1323 // resetting the path will remove any NaN or other wanky values
1293 // that might upset our scan converter. 1324 // that might upset our scan converter.
1294 devPath.reset(); 1325 devPath.reset();
1295 } 1326 }
1296 1327
1297 // if we called path.swap() we could avoid a deep copy of this path 1328 // if we called path.swap() we could avoid a deep copy of this path
1298 fClipStack.clipDevPath(devPath, op, doAA); 1329 fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1299 1330
1300 if (fAllowSimplifyClip) { 1331 if (fAllowSimplifyClip) {
1301 devPath.reset(); 1332 devPath.reset();
1302 devPath.setFillType(SkPath::kInverseEvenOdd_FillType); 1333 devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
1303 const SkClipStack* clipStack = getClipStack(); 1334 const SkClipStack* clipStack = getClipStack();
1304 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart) ; 1335 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart) ;
1305 const SkClipStack::Element* element; 1336 const SkClipStack::Element* element;
1306 while ((element = iter.next())) { 1337 while ((element = iter.next())) {
1307 SkClipStack::Element::Type type = element->getType(); 1338 SkClipStack::Element::Type type = element->getType();
1308 if (type == SkClipStack::Element::kEmpty_Type) { 1339 if (type == SkClipStack::Element::kEmpty_Type) {
1309 continue; 1340 continue;
1310 } 1341 }
1311 SkPath operand; 1342 SkPath operand;
1312 element->asPath(&operand); 1343 element->asPath(&operand);
1313 SkRegion::Op elementOp = element->getOp(); 1344 SkRegion::Op elementOp = element->getOp();
1314 if (elementOp == SkRegion::kReplace_Op) { 1345 if (elementOp == SkRegion::kReplace_Op) {
1315 devPath = operand; 1346 devPath = operand;
1316 } else { 1347 } else {
1317 Op(devPath, operand, (SkPathOp) elementOp, &devPath); 1348 Op(devPath, operand, (SkPathOp) elementOp, &devPath);
1318 } 1349 }
1319 // if the prev and curr clips disagree about aa -vs- not, favor the aa request. 1350 // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
1320 // perhaps we need an API change to avoid this sort of mixed-signals about 1351 // perhaps we need an API change to avoid this sort of mixed-signals about
1321 // clipping. 1352 // clipping.
1322 doAA |= element->isAA(); 1353 if (element->isAA()) {
1354 edgeStyle = kSoft_ClipEdgeStyle;
1355 }
1323 } 1356 }
1324 op = SkRegion::kReplace_Op; 1357 op = SkRegion::kReplace_Op;
1325 } 1358 }
1326 1359
1327 return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); 1360 clip_path_helper(this, fMCRec->fRasterClip, devPath, op, edgeStyle);
1328 } 1361 }
1329 1362
1330 bool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegio n::Op op, 1363 void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegio n::Op op,
1331 bool inverseFilled) { 1364 bool inverseFilled) {
1332 // This is for updating the clip conservatively using only bounds 1365 // This is for updating the clip conservatively using only bounds
1333 // information. 1366 // information.
1334 // Contract: 1367 // Contract:
1335 // The current clip must contain the true clip. The true 1368 // The current clip must contain the true clip. The true
1336 // clip is the clip that would have normally been computed 1369 // clip is the clip that would have normally been computed
1337 // by calls to clipPath and clipRRect 1370 // by calls to clipPath and clipRRect
1338 // Objective: 1371 // Objective:
1339 // Keep the current clip as small as possible without 1372 // Keep the current clip as small as possible without
1340 // breaking the contract, using only clip bounding rectangles 1373 // breaking the contract, using only clip bounding rectangles
1341 // (for performance). 1374 // (for performance).
1342 1375
1343 // N.B.: This *never* calls back through a virtual on canvas, so subclasses 1376 // N.B.: This *never* calls back through a virtual on canvas, so subclasses
1344 // don't have to worry about getting caught in a loop. Thus anywhere 1377 // don't have to worry about getting caught in a loop. Thus anywhere
1345 // we call a virtual method, we explicitly prefix it with 1378 // we call a virtual method, we explicitly prefix it with
1346 // SkCanvas:: to be sure to call the base-class. 1379 // SkCanvas:: to be sure to call the base-class.
1347 1380
1348 if (inverseFilled) { 1381 if (inverseFilled) {
1349 switch (op) { 1382 switch (op) {
1350 case SkRegion::kIntersect_Op: 1383 case SkRegion::kIntersect_Op:
1351 case SkRegion::kDifference_Op: 1384 case SkRegion::kDifference_Op:
1352 // These ops can only shrink the current clip. So leaving 1385 // These ops can only shrink the current clip. So leaving
1353 // the clip unchanges conservatively respects the contract. 1386 // the clip unchanges conservatively respects the contract.
1354 return this->getClipDeviceBounds(NULL); 1387 return;
1355 case SkRegion::kUnion_Op: 1388 case SkRegion::kUnion_Op:
1356 case SkRegion::kReplace_Op: 1389 case SkRegion::kReplace_Op:
1357 case SkRegion::kReverseDifference_Op: 1390 case SkRegion::kReverseDifference_Op:
1358 case SkRegion::kXOR_Op: 1391 case SkRegion::kXOR_Op:
1359 { 1392 {
1360 // These ops can grow the current clip up to the extents of 1393 // These ops can grow the current clip up to the extents of
1361 // the input clip, which is inverse filled, so we just set 1394 // the input clip, which is inverse filled, so we just set
1362 // the current clip to the device bounds. 1395 // the current clip to the device bounds.
1363 SkRect deviceBounds; 1396 SkRect deviceBounds;
1364 SkIRect deviceIBounds; 1397 SkIRect deviceIBounds;
1365 this->getDevice()->getGlobalBounds(&deviceIBounds); 1398 this->getDevice()->getGlobalBounds(&deviceIBounds);
1366 deviceBounds = SkRect::Make(deviceIBounds); 1399 deviceBounds = SkRect::Make(deviceIBounds);
1367 this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag); 1400 this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag);
1368 // set the clip in device space 1401 // set the clip in device space
1369 this->SkCanvas::setMatrix(SkMatrix::I()); 1402 this->SkCanvas::setMatrix(SkMatrix::I());
1370 bool result = this->SkCanvas::clipRect(deviceBounds, 1403 this->SkCanvas::clipRect(deviceBounds, SkRegion::kReplace_Op , false);
1371 SkRegion::kReplace_Op, false);
1372 this->SkCanvas::restore(); //pop the matrix, but keep the cl ip 1404 this->SkCanvas::restore(); //pop the matrix, but keep the cl ip
1373 return result; 1405 return;
1374 } 1406 }
1375 default: 1407 default:
1376 SkASSERT(0); // unhandled op? 1408 SkASSERT(0); // unhandled op?
1377 } 1409 }
1378 } else { 1410 } else {
1379 // Not inverse filled 1411 // Not inverse filled
1380 switch (op) { 1412 switch (op) {
1381 case SkRegion::kIntersect_Op: 1413 case SkRegion::kIntersect_Op:
1382 case SkRegion::kUnion_Op: 1414 case SkRegion::kUnion_Op:
1383 case SkRegion::kReplace_Op: 1415 case SkRegion::kReplace_Op:
1384 return this->SkCanvas::clipRect(bounds, op, false); 1416 this->SkCanvas::clipRect(bounds, op, false);
1417 return;
1385 case SkRegion::kDifference_Op: 1418 case SkRegion::kDifference_Op:
1386 // Difference can only shrink the current clip. 1419 // Difference can only shrink the current clip.
1387 // Leaving clip unchanged conservatively fullfills the contract. 1420 // Leaving clip unchanged conservatively fullfills the contract.
1388 return this->getClipDeviceBounds(NULL); 1421 return;
1389 case SkRegion::kReverseDifference_Op: 1422 case SkRegion::kReverseDifference_Op:
1390 // To reverse, we swap in the bounds with a replace op. 1423 // To reverse, we swap in the bounds with a replace op.
1391 // As with difference, leave it unchanged. 1424 // As with difference, leave it unchanged.
1392 return this->SkCanvas::clipRect(bounds, SkRegion::kReplace_Op, f alse); 1425 this->SkCanvas::clipRect(bounds, SkRegion::kReplace_Op, false);
1426 return;
1393 case SkRegion::kXOR_Op: 1427 case SkRegion::kXOR_Op:
1394 // Be conservative, based on (A XOR B) always included in (A uni on B), 1428 // Be conservative, based on (A XOR B) always included in (A uni on B),
1395 // which is always included in (bounds(A) union bounds(B)) 1429 // which is always included in (bounds(A) union bounds(B))
1396 return this->SkCanvas::clipRect(bounds, SkRegion::kUnion_Op, fal se); 1430 this->SkCanvas::clipRect(bounds, SkRegion::kUnion_Op, false);
1431 return;
1397 default: 1432 default:
1398 SkASSERT(0); // unhandled op? 1433 SkASSERT(0); // unhandled op?
1399 } 1434 }
1400 } 1435 }
1401 return true;
1402 } 1436 }
1403 1437
1404 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1438 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1439 this->onClipRegion(rgn, op);
1440 return !this->isClipEmpty();
1441 }
1442
1443 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1405 AutoValidateClip avc(this); 1444 AutoValidateClip avc(this);
1406 1445
1407 fDeviceCMDirty = true; 1446 fDeviceCMDirty = true;
1408 fCachedLocalClipBoundsDirty = true; 1447 fCachedLocalClipBoundsDirty = true;
1409 1448
1410 // todo: signal fClipStack that we have a region, and therefore (I guess) 1449 // todo: signal fClipStack that we have a region, and therefore (I guess)
1411 // we have to ignore it, and use the region directly? 1450 // we have to ignore it, and use the region directly?
1412 fClipStack.clipDevRect(rgn.getBounds(), op); 1451 fClipStack.clipDevRect(rgn.getBounds(), op);
1413 1452
1414 return fMCRec->fRasterClip->op(rgn, op); 1453 fMCRec->fRasterClip->op(rgn, op);
1415 } 1454 }
1416 1455
1417 #ifdef SK_DEBUG 1456 #ifdef SK_DEBUG
1418 void SkCanvas::validateClip() const { 1457 void SkCanvas::validateClip() const {
1419 // construct clipRgn from the clipstack 1458 // construct clipRgn from the clipstack
1420 const SkBaseDevice* device = this->getDevice(); 1459 const SkBaseDevice* device = this->getDevice();
1421 if (!device) { 1460 if (!device) {
1422 SkASSERT(this->getTotalClip().isEmpty()); 1461 SkASSERT(this->getTotalClip().isEmpty());
1423 return; 1462 return;
1424 } 1463 }
1425 1464
1426 SkIRect ir; 1465 SkIRect ir;
1427 ir.set(0, 0, device->width(), device->height()); 1466 ir.set(0, 0, device->width(), device->height());
1428 SkRasterClip tmpClip(ir); 1467 SkRasterClip tmpClip(ir);
1429 1468
1430 SkClipStack::B2TIter iter(fClipStack); 1469 SkClipStack::B2TIter iter(fClipStack);
1431 const SkClipStack::Element* element; 1470 const SkClipStack::Element* element;
1432 while ((element = iter.next()) != NULL) { 1471 while ((element = iter.next()) != NULL) {
1433 switch (element->getType()) { 1472 switch (element->getType()) {
1434 case SkClipStack::Element::kRect_Type: 1473 case SkClipStack::Element::kRect_Type:
1435 element->getRect().round(&ir); 1474 element->getRect().round(&ir);
1436 tmpClip.op(ir, element->getOp()); 1475 tmpClip.op(ir, element->getOp());
1437 break; 1476 break;
1438 case SkClipStack::Element::kEmpty_Type: 1477 case SkClipStack::Element::kEmpty_Type:
1439 tmpClip.setEmpty(); 1478 tmpClip.setEmpty();
1440 break; 1479 break;
1441 default: { 1480 default: {
1442 SkPath path; 1481 SkPath path;
1443 element->asPath(&path); 1482 element->asPath(&path);
1444 clipPathHelper(this, 1483 clip_path_helper(this, &tmpClip, path, element->getOp(), element ->isAA());
1445 &tmpClip,
1446 path,
1447 element->getOp(),
1448 element->isAA());
1449 break; 1484 break;
1450 } 1485 }
1451 } 1486 }
1452 } 1487 }
1453 1488
1454 #if 0 // enable this locally for testing 1489 #if 0 // enable this locally for testing
1455 // now compare against the current rgn 1490 // now compare against the current rgn
1456 const SkRegion& rgn = this->getTotalClip(); 1491 const SkRegion& rgn = this->getTotalClip();
1457 SkASSERT(rgn == tmpClip); 1492 SkASSERT(rgn == tmpClip);
1458 #endif 1493 #endif
(...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after
2288 return *paint; 2323 return *paint;
2289 } 2324 }
2290 2325
2291 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 2326 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
2292 int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 2327 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
2293 int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 2328 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2294 2329
2295 /////////////////////////////////////////////////////////////////////////////// 2330 ///////////////////////////////////////////////////////////////////////////////
2296 2331
2297 SkCanvas::ClipVisitor::~ClipVisitor() { } 2332 SkCanvas::ClipVisitor::~ClipVisitor() { }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698