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

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: remove debug 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
« no previous file with comments | « src/core/SkBBoxHierarchyRecord.cpp ('k') | src/core/SkPicturePlayback.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1159 void SkCanvas::resetMatrix() { 1159 void SkCanvas::resetMatrix() {
1160 SkMatrix matrix; 1160 SkMatrix matrix;
1161 1161
1162 matrix.reset(); 1162 matrix.reset();
1163 this->setMatrix(matrix); 1163 this->setMatrix(matrix);
1164 } 1164 }
1165 1165
1166 ////////////////////////////////////////////////////////////////////////////// 1166 //////////////////////////////////////////////////////////////////////////////
1167 1167
1168 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1168 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1169 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1170 this->onClipRect(rect, op, edgeStyle);
1171 return !this->isClipEmpty();
1172 }
1173
1174 void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edg eStyle) {
1169 #ifdef SK_ENABLE_CLIP_QUICKREJECT 1175 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1170 if (SkRegion::kIntersect_Op == op) { 1176 if (SkRegion::kIntersect_Op == op) {
1171 if (fMCRec->fRasterClip->isEmpty()) { 1177 if (fMCRec->fRasterClip->isEmpty()) {
1172 return false; 1178 return false;
1173 } 1179 }
1174 1180
1175 if (this->quickReject(rect)) { 1181 if (this->quickReject(rect)) {
1176 fDeviceCMDirty = true; 1182 fDeviceCMDirty = true;
1177 fCachedLocalClipBoundsDirty = true; 1183 fCachedLocalClipBoundsDirty = true;
1178 1184
1179 fClipStack.clipEmpty(); 1185 fClipStack.clipEmpty();
1180 return fMCRec->fRasterClip->setEmpty(); 1186 return fMCRec->fRasterClip->setEmpty();
1181 } 1187 }
1182 } 1188 }
1183 #endif 1189 #endif
1184 1190
1185 AutoValidateClip avc(this); 1191 AutoValidateClip avc(this);
1186 1192
1187 fDeviceCMDirty = true; 1193 fDeviceCMDirty = true;
1188 fCachedLocalClipBoundsDirty = true; 1194 fCachedLocalClipBoundsDirty = true;
1189 doAA &= fAllowSoftClip; 1195 if (!fAllowSoftClip) {
1196 edgeStyle = kHard_ClipEdgeStyle;
1197 }
1190 1198
1191 if (fMCRec->fMatrix->rectStaysRect()) { 1199 if (fMCRec->fMatrix->rectStaysRect()) {
1192 // for these simpler matrices, we can stay a rect even after applying 1200 // for these simpler matrices, we can stay a rect even after applying
1193 // the matrix. This means we don't have to a) make a path, and b) tell 1201 // the matrix. This means we don't have to a) make a path, and b) tell
1194 // the region code to scan-convert the path, only to discover that it 1202 // the region code to scan-convert the path, only to discover that it
1195 // is really just a rect. 1203 // is really just a rect.
1196 SkRect r; 1204 SkRect r;
1197 1205
1198 fMCRec->fMatrix->mapRect(&r, rect); 1206 fMCRec->fMatrix->mapRect(&r, rect);
1199 fClipStack.clipDevRect(r, op, doAA); 1207 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1200 return fMCRec->fRasterClip->op(r, op, doAA); 1208 fMCRec->fRasterClip->op(r, op, kSoft_ClipEdgeStyle == edgeStyle);
1201 } else { 1209 } else {
1202 // since we're rotated or some such thing, we convert the rect to a path 1210 // since we're rotated or some such thing, we convert the rect to a path
1203 // and clip against that, since it can handle any matrix. However, to 1211 // and clip against that, since it can handle any matrix. However, to
1204 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1212 // avoid recursion in the case where we are subclassed (e.g. Pictures)
1205 // we explicitly call "our" version of clipPath. 1213 // we explicitly call "our" version of clipPath.
1206 SkPath path; 1214 SkPath path;
1207 1215
1208 path.addRect(rect); 1216 path.addRect(rect);
1209 return this->SkCanvas::clipPath(path, op, doAA); 1217 this->SkCanvas::onClipPath(path, op, edgeStyle);
1210 } 1218 }
1211 } 1219 }
1212 1220
1213 static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip, 1221 static void clip_path_helper(const SkCanvas* canvas, SkRasterClip* currClip,
1214 const SkPath& devPath, SkRegion::Op op, bool doAA) { 1222 const SkPath& devPath, SkRegion::Op op, bool doAA) {
1215 // base is used to limit the size (and therefore memory allocation) of the 1223 // base is used to limit the size (and therefore memory allocation) of the
1216 // region that results from scan converting devPath. 1224 // region that results from scan converting devPath.
1217 SkRegion base; 1225 SkRegion base;
1218 1226
1219 if (SkRegion::kIntersect_Op == op) { 1227 if (SkRegion::kIntersect_Op == op) {
1220 // since we are intersect, we can do better (tighter) with currRgn's 1228 // since we are intersect, we can do better (tighter) with currRgn's
1221 // bounds, than just using the device. However, if currRgn is complex, 1229 // bounds, than just using the device. However, if currRgn is complex,
1222 // our region blitter may hork, so we do that case in two steps. 1230 // our region blitter may hork, so we do that case in two steps.
1223 if (currClip->isRect()) { 1231 if (currClip->isRect()) {
1224 // FIXME: we should also be able to do this when currClip->isBW(), 1232 // FIXME: we should also be able to do this when currClip->isBW(),
1225 // but relaxing the test above triggers GM asserts in 1233 // but relaxing the test above triggers GM asserts in
1226 // SkRgnBuilder::blitH(). We need to investigate what's going on. 1234 // SkRgnBuilder::blitH(). We need to investigate what's going on.
1227 return currClip->setPath(devPath, currClip->bwRgn(), doAA); 1235 currClip->setPath(devPath, currClip->bwRgn(), doAA);
1228 } else { 1236 } else {
1229 base.setRect(currClip->getBounds()); 1237 base.setRect(currClip->getBounds());
1230 SkRasterClip clip; 1238 SkRasterClip clip;
1231 clip.setPath(devPath, base, doAA); 1239 clip.setPath(devPath, base, doAA);
1232 return currClip->op(clip, op); 1240 currClip->op(clip, op);
1233 } 1241 }
1234 } else { 1242 } else {
1235 const SkBaseDevice* device = canvas->getDevice(); 1243 const SkBaseDevice* device = canvas->getDevice();
1236 if (!device) { 1244 if (!device) {
1237 return currClip->setEmpty(); 1245 currClip->setEmpty();
1246 return;
1238 } 1247 }
1239 1248
1240 base.setRect(0, 0, device->width(), device->height()); 1249 base.setRect(0, 0, device->width(), device->height());
1241 1250
1242 if (SkRegion::kReplace_Op == op) { 1251 if (SkRegion::kReplace_Op == op) {
1243 return currClip->setPath(devPath, base, doAA); 1252 currClip->setPath(devPath, base, doAA);
1244 } else { 1253 } else {
1245 SkRasterClip clip; 1254 SkRasterClip clip;
1246 clip.setPath(devPath, base, doAA); 1255 clip.setPath(devPath, base, doAA);
1247 return currClip->op(clip, op); 1256 currClip->op(clip, op);
1248 } 1257 }
1249 } 1258 }
1250 } 1259 }
1251 1260
1252 bool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 1261 bool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1262 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1253 if (rrect.isRect()) { 1263 if (rrect.isRect()) {
1254 // call the non-virtual version 1264 this->onClipRect(rrect.getBounds(), op, edgeStyle);
1255 return this->SkCanvas::clipRect(rrect.getBounds(), op, doAA); 1265 } else {
1266 this->onClipRRect(rrect, op, edgeStyle);
1256 } 1267 }
1268 return !this->isClipEmpty();
1269 }
1257 1270
1271 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1258 SkRRect transformedRRect; 1272 SkRRect transformedRRect;
1259 if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) { 1273 if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) {
1260 AutoValidateClip avc(this); 1274 AutoValidateClip avc(this);
1261 1275
1262 fDeviceCMDirty = true; 1276 fDeviceCMDirty = true;
1263 fCachedLocalClipBoundsDirty = true; 1277 fCachedLocalClipBoundsDirty = true;
1264 doAA &= fAllowSoftClip; 1278 if (!fAllowSoftClip) {
1279 edgeStyle = kHard_ClipEdgeStyle;
1280 }
1265 1281
1266 fClipStack.clipDevRRect(transformedRRect, op, doAA); 1282 fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edg eStyle);
1267 1283
1268 SkPath devPath; 1284 SkPath devPath;
1269 devPath.addRRect(transformedRRect); 1285 devPath.addRRect(transformedRRect);
1270 1286
1271 return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); 1287 clip_path_helper(this, fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeS tyle == edgeStyle);
1288 return;
1272 } 1289 }
1273 1290
1274 SkPath path; 1291 SkPath path;
1275 path.addRRect(rrect); 1292 path.addRRect(rrect);
1276 // call the non-virtual version 1293 // call the non-virtual version
1277 return this->SkCanvas::clipPath(path, op, doAA); 1294 this->SkCanvas::onClipPath(path, op, edgeStyle);
1278 } 1295 }
1279 1296
1280 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1297 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1298 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1299 SkRect r;
1300 if (!path.isInverseFillType() && path.isRect(&r)) {
1301 this->onClipRect(r, op, edgeStyle);
1302 } else {
1303 this->onClipPath(path, op, edgeStyle);
1304 }
1305
1306 return !this->isClipEmpty();
1307 }
1308
1309 void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edg eStyle) {
1281 #ifdef SK_ENABLE_CLIP_QUICKREJECT 1310 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1282 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1311 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1283 if (fMCRec->fRasterClip->isEmpty()) { 1312 if (fMCRec->fRasterClip->isEmpty()) {
1284 return false; 1313 return false;
1285 } 1314 }
1286 1315
1287 if (this->quickReject(path.getBounds())) { 1316 if (this->quickReject(path.getBounds())) {
1288 fDeviceCMDirty = true; 1317 fDeviceCMDirty = true;
1289 fCachedLocalClipBoundsDirty = true; 1318 fCachedLocalClipBoundsDirty = true;
1290 1319
1291 fClipStack.clipEmpty(); 1320 fClipStack.clipEmpty();
1292 return fMCRec->fRasterClip->setEmpty(); 1321 return fMCRec->fRasterClip->setEmpty();
1293 } 1322 }
1294 } 1323 }
1295 #endif 1324 #endif
1296 1325
1297 AutoValidateClip avc(this); 1326 AutoValidateClip avc(this);
1298 1327
1299 fDeviceCMDirty = true; 1328 fDeviceCMDirty = true;
1300 fCachedLocalClipBoundsDirty = true; 1329 fCachedLocalClipBoundsDirty = true;
1301 doAA &= fAllowSoftClip; 1330 if (!fAllowSoftClip) {
1331 edgeStyle = kHard_ClipEdgeStyle;
1332 }
1302 1333
1303 SkPath devPath; 1334 SkPath devPath;
1304 path.transform(*fMCRec->fMatrix, &devPath); 1335 path.transform(*fMCRec->fMatrix, &devPath);
1305 1336
1306 // Check if the transfomation, or the original path itself 1337 // Check if the transfomation, or the original path itself
1307 // made us empty. Note this can also happen if we contained NaN 1338 // made us empty. Note this can also happen if we contained NaN
1308 // values. computing the bounds detects this, and will set our 1339 // values. computing the bounds detects this, and will set our
1309 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1340 // bounds to empty if that is the case. (see SkRect::set(pts, count))
1310 if (devPath.getBounds().isEmpty()) { 1341 if (devPath.getBounds().isEmpty()) {
1311 // resetting the path will remove any NaN or other wanky values 1342 // resetting the path will remove any NaN or other wanky values
1312 // that might upset our scan converter. 1343 // that might upset our scan converter.
1313 devPath.reset(); 1344 devPath.reset();
1314 } 1345 }
1315 1346
1316 // if we called path.swap() we could avoid a deep copy of this path 1347 // if we called path.swap() we could avoid a deep copy of this path
1317 fClipStack.clipDevPath(devPath, op, doAA); 1348 fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1318 1349
1319 if (fAllowSimplifyClip) { 1350 if (fAllowSimplifyClip) {
1320 devPath.reset(); 1351 devPath.reset();
1321 devPath.setFillType(SkPath::kInverseEvenOdd_FillType); 1352 devPath.setFillType(SkPath::kInverseEvenOdd_FillType);
1322 const SkClipStack* clipStack = getClipStack(); 1353 const SkClipStack* clipStack = getClipStack();
1323 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart) ; 1354 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart) ;
1324 const SkClipStack::Element* element; 1355 const SkClipStack::Element* element;
1325 while ((element = iter.next())) { 1356 while ((element = iter.next())) {
1326 SkClipStack::Element::Type type = element->getType(); 1357 SkClipStack::Element::Type type = element->getType();
1327 if (type == SkClipStack::Element::kEmpty_Type) { 1358 if (type == SkClipStack::Element::kEmpty_Type) {
1328 continue; 1359 continue;
1329 } 1360 }
1330 SkPath operand; 1361 SkPath operand;
1331 element->asPath(&operand); 1362 element->asPath(&operand);
1332 SkRegion::Op elementOp = element->getOp(); 1363 SkRegion::Op elementOp = element->getOp();
1333 if (elementOp == SkRegion::kReplace_Op) { 1364 if (elementOp == SkRegion::kReplace_Op) {
1334 devPath = operand; 1365 devPath = operand;
1335 } else { 1366 } else {
1336 Op(devPath, operand, (SkPathOp) elementOp, &devPath); 1367 Op(devPath, operand, (SkPathOp) elementOp, &devPath);
1337 } 1368 }
1338 // if the prev and curr clips disagree about aa -vs- not, favor the aa request. 1369 // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
1339 // perhaps we need an API change to avoid this sort of mixed-signals about 1370 // perhaps we need an API change to avoid this sort of mixed-signals about
1340 // clipping. 1371 // clipping.
1341 doAA |= element->isAA(); 1372 if (element->isAA()) {
1373 edgeStyle = kSoft_ClipEdgeStyle;
1374 }
1342 } 1375 }
1343 op = SkRegion::kReplace_Op; 1376 op = SkRegion::kReplace_Op;
1344 } 1377 }
1345 1378
1346 return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); 1379 clip_path_helper(this, fMCRec->fRasterClip, devPath, op, edgeStyle);
1347 } 1380 }
1348 1381
1349 bool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegio n::Op op, 1382 bool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegio n::Op op,
1350 bool inverseFilled) { 1383 bool inverseFilled) {
1351 // This is for updating the clip conservatively using only bounds 1384 // This is for updating the clip conservatively using only bounds
1352 // information. 1385 // information.
1353 // Contract: 1386 // Contract:
1354 // The current clip must contain the true clip. The true 1387 // The current clip must contain the true clip. The true
1355 // clip is the clip that would have normally been computed 1388 // clip is the clip that would have normally been computed
1356 // by calls to clipPath and clipRRect 1389 // by calls to clipPath and clipRRect
1357 // Objective: 1390 // Objective:
1358 // Keep the current clip as small as possible without 1391 // Keep the current clip as small as possible without
1359 // breaking the contract, using only clip bounding rectangles 1392 // breaking the contract, using only clip bounding rectangles
1360 // (for performance). 1393 // (for performance).
1361 1394
1362 // N.B.: This *never* calls back through a virtual on canvas, so subclasses 1395 // N.B.: This *never* calls back through a virtual on canvas, so subclasses
1363 // don't have to worry about getting caught in a loop. Thus anywhere 1396 // don't have to worry about getting caught in a loop. Thus anywhere
1364 // we call a virtual method, we explicitly prefix it with 1397 // we call a virtual method, we explicitly prefix it with
1365 // SkCanvas:: to be sure to call the base-class. 1398 // SkCanvas:: to be sure to call the base-class.
1366 1399
1367 if (inverseFilled) { 1400 if (inverseFilled) {
1368 switch (op) { 1401 switch (op) {
1369 case SkRegion::kIntersect_Op: 1402 case SkRegion::kIntersect_Op:
1370 case SkRegion::kDifference_Op: 1403 case SkRegion::kDifference_Op:
1371 // These ops can only shrink the current clip. So leaving 1404 // These ops can only shrink the current clip. So leaving
1372 // the clip unchanges conservatively respects the contract. 1405 // the clip unchanged conservatively respects the contract.
1373 return this->getClipDeviceBounds(NULL); 1406 break;
1374 case SkRegion::kUnion_Op: 1407 case SkRegion::kUnion_Op:
1375 case SkRegion::kReplace_Op: 1408 case SkRegion::kReplace_Op:
1376 case SkRegion::kReverseDifference_Op: 1409 case SkRegion::kReverseDifference_Op:
1377 case SkRegion::kXOR_Op: 1410 case SkRegion::kXOR_Op: {
1378 {
1379 // These ops can grow the current clip up to the extents of 1411 // These ops can grow the current clip up to the extents of
1380 // the input clip, which is inverse filled, so we just set 1412 // the input clip, which is inverse filled, so we just set
1381 // the current clip to the device bounds. 1413 // the current clip to the device bounds.
1382 SkRect deviceBounds; 1414 SkRect deviceBounds;
1383 SkIRect deviceIBounds; 1415 SkIRect deviceIBounds;
1384 this->getDevice()->getGlobalBounds(&deviceIBounds); 1416 this->getDevice()->getGlobalBounds(&deviceIBounds);
1385 deviceBounds = SkRect::Make(deviceIBounds); 1417 deviceBounds = SkRect::Make(deviceIBounds);
1386 this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag); 1418 this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag);
1387 // set the clip in device space 1419 // set the clip in device space
1388 this->SkCanvas::setMatrix(SkMatrix::I()); 1420 this->SkCanvas::setMatrix(SkMatrix::I());
1389 bool result = this->SkCanvas::clipRect(deviceBounds, 1421 this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_ Op,
1390 SkRegion::kReplace_Op, false); 1422 kHard_ClipEdgeStyle);
1391 this->SkCanvas::restore(); //pop the matrix, but keep the cl ip 1423 this->SkCanvas::restore(); //pop the matrix, but keep the cl ip
1392 return result; 1424 break;
1393 } 1425 }
1394 default: 1426 default:
1395 SkASSERT(0); // unhandled op? 1427 SkASSERT(0); // unhandled op?
1396 } 1428 }
1397 } else { 1429 } else {
1398 // Not inverse filled 1430 // Not inverse filled
1399 switch (op) { 1431 switch (op) {
1400 case SkRegion::kIntersect_Op: 1432 case SkRegion::kIntersect_Op:
1401 case SkRegion::kUnion_Op: 1433 case SkRegion::kUnion_Op:
1402 case SkRegion::kReplace_Op: 1434 case SkRegion::kReplace_Op:
1403 return this->SkCanvas::clipRect(bounds, op, false); 1435 this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle);
1436 break;
1404 case SkRegion::kDifference_Op: 1437 case SkRegion::kDifference_Op:
1405 // Difference can only shrink the current clip. 1438 // Difference can only shrink the current clip.
1406 // Leaving clip unchanged conservatively fullfills the contract. 1439 // Leaving clip unchanged conservatively fullfills the contract.
1407 return this->getClipDeviceBounds(NULL); 1440 break;
1408 case SkRegion::kReverseDifference_Op: 1441 case SkRegion::kReverseDifference_Op:
1409 // To reverse, we swap in the bounds with a replace op. 1442 // To reverse, we swap in the bounds with a replace op.
1410 // As with difference, leave it unchanged. 1443 // As with difference, leave it unchanged.
1411 return this->SkCanvas::clipRect(bounds, SkRegion::kReplace_Op, f alse); 1444 this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ ClipEdgeStyle);
1445 break;
1412 case SkRegion::kXOR_Op: 1446 case SkRegion::kXOR_Op:
1413 // Be conservative, based on (A XOR B) always included in (A uni on B), 1447 // Be conservative, based on (A XOR B) always included in (A uni on B),
1414 // which is always included in (bounds(A) union bounds(B)) 1448 // which is always included in (bounds(A) union bounds(B))
1415 return this->SkCanvas::clipRect(bounds, SkRegion::kUnion_Op, fal se); 1449 this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_Cl ipEdgeStyle);
1450 break;
1416 default: 1451 default:
1417 SkASSERT(0); // unhandled op? 1452 SkASSERT(0); // unhandled op?
1418 } 1453 }
1419 } 1454 }
1420 return true; 1455
1456 return !this->isClipEmpty();
1421 } 1457 }
1422 1458
1423 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1459 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1460 this->onClipRegion(rgn, op);
1461 return !this->isClipEmpty();
1462 }
1463
1464 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1424 AutoValidateClip avc(this); 1465 AutoValidateClip avc(this);
1425 1466
1426 fDeviceCMDirty = true; 1467 fDeviceCMDirty = true;
1427 fCachedLocalClipBoundsDirty = true; 1468 fCachedLocalClipBoundsDirty = true;
1428 1469
1429 // todo: signal fClipStack that we have a region, and therefore (I guess) 1470 // todo: signal fClipStack that we have a region, and therefore (I guess)
1430 // we have to ignore it, and use the region directly? 1471 // we have to ignore it, and use the region directly?
1431 fClipStack.clipDevRect(rgn.getBounds(), op); 1472 fClipStack.clipDevRect(rgn.getBounds(), op);
1432 1473
1433 return fMCRec->fRasterClip->op(rgn, op); 1474 fMCRec->fRasterClip->op(rgn, op);
1434 } 1475 }
1435 1476
1436 #ifdef SK_DEBUG 1477 #ifdef SK_DEBUG
1437 void SkCanvas::validateClip() const { 1478 void SkCanvas::validateClip() const {
1438 // construct clipRgn from the clipstack 1479 // construct clipRgn from the clipstack
1439 const SkBaseDevice* device = this->getDevice(); 1480 const SkBaseDevice* device = this->getDevice();
1440 if (!device) { 1481 if (!device) {
1441 SkASSERT(this->getTotalClip().isEmpty()); 1482 SkASSERT(this->getTotalClip().isEmpty());
1442 return; 1483 return;
1443 } 1484 }
1444 1485
1445 SkIRect ir; 1486 SkIRect ir;
1446 ir.set(0, 0, device->width(), device->height()); 1487 ir.set(0, 0, device->width(), device->height());
1447 SkRasterClip tmpClip(ir); 1488 SkRasterClip tmpClip(ir);
1448 1489
1449 SkClipStack::B2TIter iter(fClipStack); 1490 SkClipStack::B2TIter iter(fClipStack);
1450 const SkClipStack::Element* element; 1491 const SkClipStack::Element* element;
1451 while ((element = iter.next()) != NULL) { 1492 while ((element = iter.next()) != NULL) {
1452 switch (element->getType()) { 1493 switch (element->getType()) {
1453 case SkClipStack::Element::kRect_Type: 1494 case SkClipStack::Element::kRect_Type:
1454 element->getRect().round(&ir); 1495 element->getRect().round(&ir);
1455 tmpClip.op(ir, element->getOp()); 1496 tmpClip.op(ir, element->getOp());
1456 break; 1497 break;
1457 case SkClipStack::Element::kEmpty_Type: 1498 case SkClipStack::Element::kEmpty_Type:
1458 tmpClip.setEmpty(); 1499 tmpClip.setEmpty();
1459 break; 1500 break;
1460 default: { 1501 default: {
1461 SkPath path; 1502 SkPath path;
1462 element->asPath(&path); 1503 element->asPath(&path);
1463 clipPathHelper(this, 1504 clip_path_helper(this, &tmpClip, path, element->getOp(), element ->isAA());
1464 &tmpClip,
1465 path,
1466 element->getOp(),
1467 element->isAA());
1468 break; 1505 break;
1469 } 1506 }
1470 } 1507 }
1471 } 1508 }
1472 1509
1473 #if 0 // enable this locally for testing 1510 #if 0 // enable this locally for testing
1474 // now compare against the current rgn 1511 // now compare against the current rgn
1475 const SkRegion& rgn = this->getTotalClip(); 1512 const SkRegion& rgn = this->getTotalClip();
1476 SkASSERT(rgn == tmpClip); 1513 SkASSERT(rgn == tmpClip);
1477 #endif 1514 #endif
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1536 return false; 1573 return false;
1537 } 1574 }
1538 } 1575 }
1539 1576
1540 bool SkCanvas::quickReject(const SkPath& path) const { 1577 bool SkCanvas::quickReject(const SkPath& path) const {
1541 return path.isEmpty() || this->quickReject(path.getBounds()); 1578 return path.isEmpty() || this->quickReject(path.getBounds());
1542 } 1579 }
1543 1580
1544 bool SkCanvas::getClipBounds(SkRect* bounds) const { 1581 bool SkCanvas::getClipBounds(SkRect* bounds) const {
1545 SkIRect ibounds; 1582 SkIRect ibounds;
1546 if (!getClipDeviceBounds(&ibounds)) { 1583 if (!this->getClipDeviceBounds(&ibounds)) {
1547 return false; 1584 return false;
1548 } 1585 }
1549 1586
1550 SkMatrix inverse; 1587 SkMatrix inverse;
1551 // if we can't invert the CTM, we can't return local clip bounds 1588 // if we can't invert the CTM, we can't return local clip bounds
1552 if (!fMCRec->fMatrix->invert(&inverse)) { 1589 if (!fMCRec->fMatrix->invert(&inverse)) {
1553 if (bounds) { 1590 if (bounds) {
1554 bounds->setEmpty(); 1591 bounds->setEmpty();
1555 } 1592 }
1556 return false; 1593 return false;
(...skipping 24 matching lines...) Expand all
1581 *bounds = clip.getBounds(); 1618 *bounds = clip.getBounds();
1582 } 1619 }
1583 return true; 1620 return true;
1584 } 1621 }
1585 1622
1586 const SkMatrix& SkCanvas::getTotalMatrix() const { 1623 const SkMatrix& SkCanvas::getTotalMatrix() const {
1587 return *fMCRec->fMatrix; 1624 return *fMCRec->fMatrix;
1588 } 1625 }
1589 1626
1590 SkCanvas::ClipType SkCanvas::getClipType() const { 1627 SkCanvas::ClipType SkCanvas::getClipType() const {
1591 if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType; 1628 if (fMCRec->fRasterClip->isEmpty()) {
1592 if (fMCRec->fRasterClip->isRect()) return kRect_ClipType; 1629 return kEmpty_ClipType;
1630 }
1631 if (fMCRec->fRasterClip->isRect()) {
1632 return kRect_ClipType;
1633 }
1593 return kComplex_ClipType; 1634 return kComplex_ClipType;
1594 } 1635 }
1595 1636
1596 const SkRegion& SkCanvas::getTotalClip() const { 1637 const SkRegion& SkCanvas::getTotalClip() const {
1597 return fMCRec->fRasterClip->forceGetBW(); 1638 return fMCRec->fRasterClip->forceGetBW();
1598 } 1639 }
1599 1640
1600 SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) { 1641 SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
1601 SkBaseDevice* device = this->getTopDevice(); 1642 SkBaseDevice* device = this->getTopDevice();
1602 return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL; 1643 return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
(...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after
2347 if (!bitmap.allocPixels(info)) { 2388 if (!bitmap.allocPixels(info)) {
2348 return NULL; 2389 return NULL;
2349 } 2390 }
2350 2391
2351 // should this functionality be moved into allocPixels()? 2392 // should this functionality be moved into allocPixels()?
2352 if (!bitmap.info().isOpaque()) { 2393 if (!bitmap.info().isOpaque()) {
2353 bitmap.eraseColor(0); 2394 bitmap.eraseColor(0);
2354 } 2395 }
2355 return SkNEW_ARGS(SkCanvas, (bitmap)); 2396 return SkNEW_ARGS(SkCanvas, (bitmap));
2356 } 2397 }
OLDNEW
« no previous file with comments | « src/core/SkBBoxHierarchyRecord.cpp ('k') | src/core/SkPicturePlayback.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698