| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2008 The Android Open Source Project | 2 * Copyright 2008 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 | 8 |
| 9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
| 10 #include "SkBitmapDevice.h" | 10 #include "SkBitmapDevice.h" |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 | 182 |
| 183 /* This is the record we keep for each save/restore level in the stack. | 183 /* This is the record we keep for each save/restore level in the stack. |
| 184 Since a level optionally copies the matrix and/or stack, we have pointers | 184 Since a level optionally copies the matrix and/or stack, we have pointers |
| 185 for these fields. If the value is copied for this level, the copy is | 185 for these fields. If the value is copied for this level, the copy is |
| 186 stored in the ...Storage field, and the pointer points to that. If the | 186 stored in the ...Storage field, and the pointer points to that. If the |
| 187 value is not copied for this level, we ignore ...Storage, and just point | 187 value is not copied for this level, we ignore ...Storage, and just point |
| 188 at the corresponding value in the previous level in the stack. | 188 at the corresponding value in the previous level in the stack. |
| 189 */ | 189 */ |
| 190 class SkCanvas::MCRec { | 190 class SkCanvas::MCRec { |
| 191 public: | 191 public: |
| 192 SkMatrix* fMatrix; // points to either fMatrixStorage or prev M
CRec | 192 SkMatrix fMatrix; |
| 193 SkRasterClip* fRasterClip; // points to either fRegionStorage or prev M
CRec | 193 SkRasterClip fRasterClip; |
| 194 SkDrawFilter* fFilter; // the current filter (or null) | 194 SkDrawFilter* fFilter; // the current filter (or null) |
| 195 | 195 |
| 196 DeviceCM* fLayer; | 196 DeviceCM* fLayer; |
| 197 /* If there are any layers in the stack, this points to the top-most | 197 /* If there are any layers in the stack, this points to the top-most |
| 198 one that is at or below this level in the stack (so we know what | 198 one that is at or below this level in the stack (so we know what |
| 199 bitmap/device to draw into from this level. This value is NOT | 199 bitmap/device to draw into from this level. This value is NOT |
| 200 reference counted, since the real owner is either our fLayer field, | 200 reference counted, since the real owner is either our fLayer field, |
| 201 or a previous one in a lower level.) | 201 or a previous one in a lower level.) |
| 202 */ | 202 */ |
| 203 DeviceCM* fTopLayer; | 203 DeviceCM* fTopLayer; |
| 204 | 204 |
| 205 MCRec(const MCRec* prev) { | 205 MCRec(const MCRec* prev) { |
| 206 if (NULL != prev) { | 206 if (NULL != prev) { |
| 207 fMatrixStorage = *prev->fMatrix; | 207 fMatrix = prev->fMatrix; |
| 208 fMatrix = &fMatrixStorage; | 208 fRasterClip = prev->fRasterClip; |
| 209 | |
| 210 fRasterClipStorage = *prev->fRasterClip; | |
| 211 fRasterClip = &fRasterClipStorage; | |
| 212 | 209 |
| 213 fFilter = prev->fFilter; | 210 fFilter = prev->fFilter; |
| 214 SkSafeRef(fFilter); | 211 SkSafeRef(fFilter); |
| 215 | 212 |
| 216 fTopLayer = prev->fTopLayer; | 213 fTopLayer = prev->fTopLayer; |
| 217 } else { // no prev | 214 } else { // no prev |
| 218 fMatrixStorage.reset(); | 215 fMatrix.reset(); |
| 219 | |
| 220 fMatrix = &fMatrixStorage; | |
| 221 fRasterClip = &fRasterClipStorage; | |
| 222 fFilter = NULL; | 216 fFilter = NULL; |
| 223 fTopLayer = NULL; | 217 fTopLayer = NULL; |
| 224 } | 218 } |
| 225 fLayer = NULL; | 219 fLayer = NULL; |
| 226 | 220 |
| 227 // don't bother initializing fNext | 221 // don't bother initializing fNext |
| 228 inc_rec(); | 222 inc_rec(); |
| 229 } | 223 } |
| 230 ~MCRec() { | 224 ~MCRec() { |
| 231 SkSafeUnref(fFilter); | 225 SkSafeUnref(fFilter); |
| 232 SkDELETE(fLayer); | 226 SkDELETE(fLayer); |
| 233 dec_rec(); | 227 dec_rec(); |
| 234 } | 228 } |
| 235 | |
| 236 private: | |
| 237 SkMatrix fMatrixStorage; | |
| 238 SkRasterClip fRasterClipStorage; | |
| 239 }; | 229 }; |
| 240 | 230 |
| 241 class SkDrawIter : public SkDraw { | 231 class SkDrawIter : public SkDraw { |
| 242 public: | 232 public: |
| 243 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { | 233 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { |
| 244 canvas = canvas->canvasForDrawIter(); | 234 canvas = canvas->canvasForDrawIter(); |
| 245 fCanvas = canvas; | 235 fCanvas = canvas; |
| 246 canvas->updateDeviceCMCache(); | 236 canvas->updateDeviceCMCache(); |
| 247 | 237 |
| 248 fClipStack = &canvas->fClipStack; | 238 fClipStack = &canvas->fClipStack; |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 accurately take advantage of the new device bounds. | 579 accurately take advantage of the new device bounds. |
| 590 */ | 580 */ |
| 591 | 581 |
| 592 SkIRect bounds; | 582 SkIRect bounds; |
| 593 if (device) { | 583 if (device) { |
| 594 bounds.set(0, 0, device->width(), device->height()); | 584 bounds.set(0, 0, device->width(), device->height()); |
| 595 } else { | 585 } else { |
| 596 bounds.setEmpty(); | 586 bounds.setEmpty(); |
| 597 } | 587 } |
| 598 // now jam our 1st clip to be bounds, and intersect the rest with that | 588 // now jam our 1st clip to be bounds, and intersect the rest with that |
| 599 rec->fRasterClip->setRect(bounds); | 589 rec->fRasterClip.setRect(bounds); |
| 600 while ((rec = (MCRec*)iter.next()) != NULL) { | 590 while ((rec = (MCRec*)iter.next()) != NULL) { |
| 601 (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op); | 591 (void)rec->fRasterClip.op(bounds, SkRegion::kIntersect_Op); |
| 602 } | 592 } |
| 603 | 593 |
| 604 return device; | 594 return device; |
| 605 } | 595 } |
| 606 | 596 |
| 607 bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) { | 597 bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) { |
| 608 if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) { | 598 if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) { |
| 609 return false; | 599 return false; |
| 610 } | 600 } |
| 611 | 601 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 | 743 |
| 754 SkCanvas* SkCanvas::canvasForDrawIter() { | 744 SkCanvas* SkCanvas::canvasForDrawIter() { |
| 755 return this; | 745 return this; |
| 756 } | 746 } |
| 757 | 747 |
| 758 ////////////////////////////////////////////////////////////////////////////// | 748 ////////////////////////////////////////////////////////////////////////////// |
| 759 | 749 |
| 760 void SkCanvas::updateDeviceCMCache() { | 750 void SkCanvas::updateDeviceCMCache() { |
| 761 if (fDeviceCMDirty) { | 751 if (fDeviceCMDirty) { |
| 762 const SkMatrix& totalMatrix = this->getTotalMatrix(); | 752 const SkMatrix& totalMatrix = this->getTotalMatrix(); |
| 763 const SkRasterClip& totalClip = *fMCRec->fRasterClip; | 753 const SkRasterClip& totalClip = fMCRec->fRasterClip; |
| 764 DeviceCM* layer = fMCRec->fTopLayer; | 754 DeviceCM* layer = fMCRec->fTopLayer; |
| 765 | 755 |
| 766 if (NULL == layer->fNext) { // only one layer | 756 if (NULL == layer->fNext) { // only one layer |
| 767 layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); | 757 layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); |
| 768 } else { | 758 } else { |
| 769 SkRasterClip clip(totalClip); | 759 SkRasterClip clip(totalClip); |
| 770 do { | 760 do { |
| 771 layer->updateMC(totalMatrix, clip, fClipStack, &clip); | 761 layer->updateMC(totalMatrix, clip, fClipStack, &clip); |
| 772 } while ((layer = layer->fNext) != NULL); | 762 } while ((layer = layer->fNext) != NULL); |
| 773 } | 763 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 804 | 794 |
| 805 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, | 795 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, |
| 806 SkIRect* intersection, const SkImageFilter* image
Filter) { | 796 SkIRect* intersection, const SkImageFilter* image
Filter) { |
| 807 SkIRect clipBounds; | 797 SkIRect clipBounds; |
| 808 SkRegion::Op op = SkRegion::kIntersect_Op; | 798 SkRegion::Op op = SkRegion::kIntersect_Op; |
| 809 if (!this->getClipDeviceBounds(&clipBounds)) { | 799 if (!this->getClipDeviceBounds(&clipBounds)) { |
| 810 return false; | 800 return false; |
| 811 } | 801 } |
| 812 | 802 |
| 813 if (imageFilter) { | 803 if (imageFilter) { |
| 814 imageFilter->filterBounds(clipBounds, *fMCRec->fMatrix, &clipBounds); | 804 imageFilter->filterBounds(clipBounds, fMCRec->fMatrix, &clipBounds); |
| 815 // Filters may grow the bounds beyond the device bounds. | 805 // Filters may grow the bounds beyond the device bounds. |
| 816 op = SkRegion::kReplace_Op; | 806 op = SkRegion::kReplace_Op; |
| 817 } | 807 } |
| 818 SkIRect ir; | 808 SkIRect ir; |
| 819 if (NULL != bounds) { | 809 if (NULL != bounds) { |
| 820 SkRect r; | 810 SkRect r; |
| 821 | 811 |
| 822 this->getTotalMatrix().mapRect(&r, *bounds); | 812 this->getTotalMatrix().mapRect(&r, *bounds); |
| 823 r.roundOut(&ir); | 813 r.roundOut(&ir); |
| 824 // early exit if the layer's bounds are clipped out | 814 // early exit if the layer's bounds are clipped out |
| 825 if (!ir.intersect(clipBounds)) { | 815 if (!ir.intersect(clipBounds)) { |
| 826 if (bounds_affects_clip(flags)) { | 816 if (bounds_affects_clip(flags)) { |
| 827 fMCRec->fRasterClip->setEmpty(); | 817 fMCRec->fRasterClip.setEmpty(); |
| 828 } | 818 } |
| 829 return false; | 819 return false; |
| 830 } | 820 } |
| 831 } else { // no user bounds, so just use the clip | 821 } else { // no user bounds, so just use the clip |
| 832 ir = clipBounds; | 822 ir = clipBounds; |
| 833 } | 823 } |
| 834 | 824 |
| 835 if (bounds_affects_clip(flags)) { | 825 if (bounds_affects_clip(flags)) { |
| 836 fClipStack.clipDevRect(ir, op); | 826 fClipStack.clipDevRect(ir, op); |
| 837 // early exit if the clip is now empty | 827 // early exit if the clip is now empty |
| 838 if (!fMCRec->fRasterClip->op(ir, op)) { | 828 if (!fMCRec->fRasterClip.op(ir, op)) { |
| 839 return false; | 829 return false; |
| 840 } | 830 } |
| 841 } | 831 } |
| 842 | 832 |
| 843 if (intersection) { | 833 if (intersection) { |
| 844 *intersection = ir; | 834 *intersection = ir; |
| 845 } | 835 } |
| 846 return true; | 836 return true; |
| 847 } | 837 } |
| 848 | 838 |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1277 this->concat(m); | 1267 this->concat(m); |
| 1278 } | 1268 } |
| 1279 | 1269 |
| 1280 void SkCanvas::concat(const SkMatrix& matrix) { | 1270 void SkCanvas::concat(const SkMatrix& matrix) { |
| 1281 if (matrix.isIdentity()) { | 1271 if (matrix.isIdentity()) { |
| 1282 return; | 1272 return; |
| 1283 } | 1273 } |
| 1284 | 1274 |
| 1285 fDeviceCMDirty = true; | 1275 fDeviceCMDirty = true; |
| 1286 fCachedLocalClipBoundsDirty = true; | 1276 fCachedLocalClipBoundsDirty = true; |
| 1287 fMCRec->fMatrix->preConcat(matrix); | 1277 fMCRec->fMatrix.preConcat(matrix); |
| 1288 | 1278 |
| 1289 this->didConcat(matrix); | 1279 this->didConcat(matrix); |
| 1290 } | 1280 } |
| 1291 | 1281 |
| 1292 void SkCanvas::setMatrix(const SkMatrix& matrix) { | 1282 void SkCanvas::setMatrix(const SkMatrix& matrix) { |
| 1293 fDeviceCMDirty = true; | 1283 fDeviceCMDirty = true; |
| 1294 fCachedLocalClipBoundsDirty = true; | 1284 fCachedLocalClipBoundsDirty = true; |
| 1295 *fMCRec->fMatrix = matrix; | 1285 fMCRec->fMatrix = matrix; |
| 1296 this->didSetMatrix(matrix); | 1286 this->didSetMatrix(matrix); |
| 1297 } | 1287 } |
| 1298 | 1288 |
| 1299 void SkCanvas::resetMatrix() { | 1289 void SkCanvas::resetMatrix() { |
| 1300 SkMatrix matrix; | 1290 SkMatrix matrix; |
| 1301 | 1291 |
| 1302 matrix.reset(); | 1292 matrix.reset(); |
| 1303 this->setMatrix(matrix); | 1293 this->setMatrix(matrix); |
| 1304 } | 1294 } |
| 1305 | 1295 |
| 1306 ////////////////////////////////////////////////////////////////////////////// | 1296 ////////////////////////////////////////////////////////////////////////////// |
| 1307 | 1297 |
| 1308 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { | 1298 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { |
| 1309 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; | 1299 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; |
| 1310 this->onClipRect(rect, op, edgeStyle); | 1300 this->onClipRect(rect, op, edgeStyle); |
| 1311 } | 1301 } |
| 1312 | 1302 |
| 1313 void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edg
eStyle) { | 1303 void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edg
eStyle) { |
| 1314 #ifdef SK_ENABLE_CLIP_QUICKREJECT | 1304 #ifdef SK_ENABLE_CLIP_QUICKREJECT |
| 1315 if (SkRegion::kIntersect_Op == op) { | 1305 if (SkRegion::kIntersect_Op == op) { |
| 1316 if (fMCRec->fRasterClip->isEmpty()) { | 1306 if (fMCRec->fRasterClip.isEmpty()) { |
| 1317 return false; | 1307 return false; |
| 1318 } | 1308 } |
| 1319 | 1309 |
| 1320 if (this->quickReject(rect)) { | 1310 if (this->quickReject(rect)) { |
| 1321 fDeviceCMDirty = true; | 1311 fDeviceCMDirty = true; |
| 1322 fCachedLocalClipBoundsDirty = true; | 1312 fCachedLocalClipBoundsDirty = true; |
| 1323 | 1313 |
| 1324 fClipStack.clipEmpty(); | 1314 fClipStack.clipEmpty(); |
| 1325 return fMCRec->fRasterClip->setEmpty(); | 1315 return fMCRec->fRasterClip.setEmpty(); |
| 1326 } | 1316 } |
| 1327 } | 1317 } |
| 1328 #endif | 1318 #endif |
| 1329 | 1319 |
| 1330 AutoValidateClip avc(this); | 1320 AutoValidateClip avc(this); |
| 1331 | 1321 |
| 1332 fDeviceCMDirty = true; | 1322 fDeviceCMDirty = true; |
| 1333 fCachedLocalClipBoundsDirty = true; | 1323 fCachedLocalClipBoundsDirty = true; |
| 1334 if (!fAllowSoftClip) { | 1324 if (!fAllowSoftClip) { |
| 1335 edgeStyle = kHard_ClipEdgeStyle; | 1325 edgeStyle = kHard_ClipEdgeStyle; |
| 1336 } | 1326 } |
| 1337 | 1327 |
| 1338 if (fMCRec->fMatrix->rectStaysRect()) { | 1328 if (fMCRec->fMatrix.rectStaysRect()) { |
| 1339 // for these simpler matrices, we can stay a rect even after applying | 1329 // for these simpler matrices, we can stay a rect even after applying |
| 1340 // the matrix. This means we don't have to a) make a path, and b) tell | 1330 // the matrix. This means we don't have to a) make a path, and b) tell |
| 1341 // the region code to scan-convert the path, only to discover that it | 1331 // the region code to scan-convert the path, only to discover that it |
| 1342 // is really just a rect. | 1332 // is really just a rect. |
| 1343 SkRect r; | 1333 SkRect r; |
| 1344 | 1334 |
| 1345 fMCRec->fMatrix->mapRect(&r, rect); | 1335 fMCRec->fMatrix.mapRect(&r, rect); |
| 1346 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); | 1336 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); |
| 1347 fMCRec->fRasterClip->op(r, op, kSoft_ClipEdgeStyle == edgeStyle); | 1337 fMCRec->fRasterClip.op(r, op, kSoft_ClipEdgeStyle == edgeStyle); |
| 1348 } else { | 1338 } else { |
| 1349 // since we're rotated or some such thing, we convert the rect to a path | 1339 // since we're rotated or some such thing, we convert the rect to a path |
| 1350 // and clip against that, since it can handle any matrix. However, to | 1340 // and clip against that, since it can handle any matrix. However, to |
| 1351 // avoid recursion in the case where we are subclassed (e.g. Pictures) | 1341 // avoid recursion in the case where we are subclassed (e.g. Pictures) |
| 1352 // we explicitly call "our" version of clipPath. | 1342 // we explicitly call "our" version of clipPath. |
| 1353 SkPath path; | 1343 SkPath path; |
| 1354 | 1344 |
| 1355 path.addRect(rect); | 1345 path.addRect(rect); |
| 1356 this->SkCanvas::onClipPath(path, op, edgeStyle); | 1346 this->SkCanvas::onClipPath(path, op, edgeStyle); |
| 1357 } | 1347 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1396 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; | 1386 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; |
| 1397 if (rrect.isRect()) { | 1387 if (rrect.isRect()) { |
| 1398 this->onClipRect(rrect.getBounds(), op, edgeStyle); | 1388 this->onClipRect(rrect.getBounds(), op, edgeStyle); |
| 1399 } else { | 1389 } else { |
| 1400 this->onClipRRect(rrect, op, edgeStyle); | 1390 this->onClipRRect(rrect, op, edgeStyle); |
| 1401 } | 1391 } |
| 1402 } | 1392 } |
| 1403 | 1393 |
| 1404 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle
edgeStyle) { | 1394 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle
edgeStyle) { |
| 1405 SkRRect transformedRRect; | 1395 SkRRect transformedRRect; |
| 1406 if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) { | 1396 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { |
| 1407 AutoValidateClip avc(this); | 1397 AutoValidateClip avc(this); |
| 1408 | 1398 |
| 1409 fDeviceCMDirty = true; | 1399 fDeviceCMDirty = true; |
| 1410 fCachedLocalClipBoundsDirty = true; | 1400 fCachedLocalClipBoundsDirty = true; |
| 1411 if (!fAllowSoftClip) { | 1401 if (!fAllowSoftClip) { |
| 1412 edgeStyle = kHard_ClipEdgeStyle; | 1402 edgeStyle = kHard_ClipEdgeStyle; |
| 1413 } | 1403 } |
| 1414 | 1404 |
| 1415 fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edg
eStyle); | 1405 fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edg
eStyle); |
| 1416 | 1406 |
| 1417 SkPath devPath; | 1407 SkPath devPath; |
| 1418 devPath.addRRect(transformedRRect); | 1408 devPath.addRRect(transformedRRect); |
| 1419 | 1409 |
| 1420 clip_path_helper(this, fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeS
tyle == edgeStyle); | 1410 clip_path_helper(this, &fMCRec->fRasterClip, devPath, op, kSoft_ClipEdge
Style == edgeStyle); |
| 1421 return; | 1411 return; |
| 1422 } | 1412 } |
| 1423 | 1413 |
| 1424 SkPath path; | 1414 SkPath path; |
| 1425 path.addRRect(rrect); | 1415 path.addRRect(rrect); |
| 1426 // call the non-virtual version | 1416 // call the non-virtual version |
| 1427 this->SkCanvas::onClipPath(path, op, edgeStyle); | 1417 this->SkCanvas::onClipPath(path, op, edgeStyle); |
| 1428 } | 1418 } |
| 1429 | 1419 |
| 1430 void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { | 1420 void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { |
| 1431 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; | 1421 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; |
| 1432 SkRect r; | 1422 SkRect r; |
| 1433 if (!path.isInverseFillType() && path.isRect(&r)) { | 1423 if (!path.isInverseFillType() && path.isRect(&r)) { |
| 1434 this->onClipRect(r, op, edgeStyle); | 1424 this->onClipRect(r, op, edgeStyle); |
| 1435 } else { | 1425 } else { |
| 1436 this->onClipPath(path, op, edgeStyle); | 1426 this->onClipPath(path, op, edgeStyle); |
| 1437 } | 1427 } |
| 1438 } | 1428 } |
| 1439 | 1429 |
| 1440 void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edg
eStyle) { | 1430 void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edg
eStyle) { |
| 1441 #ifdef SK_ENABLE_CLIP_QUICKREJECT | 1431 #ifdef SK_ENABLE_CLIP_QUICKREJECT |
| 1442 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { | 1432 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { |
| 1443 if (fMCRec->fRasterClip->isEmpty()) { | 1433 if (fMCRec->fRasterClip.isEmpty()) { |
| 1444 return false; | 1434 return false; |
| 1445 } | 1435 } |
| 1446 | 1436 |
| 1447 if (this->quickReject(path.getBounds())) { | 1437 if (this->quickReject(path.getBounds())) { |
| 1448 fDeviceCMDirty = true; | 1438 fDeviceCMDirty = true; |
| 1449 fCachedLocalClipBoundsDirty = true; | 1439 fCachedLocalClipBoundsDirty = true; |
| 1450 | 1440 |
| 1451 fClipStack.clipEmpty(); | 1441 fClipStack.clipEmpty(); |
| 1452 return fMCRec->fRasterClip->setEmpty(); | 1442 return fMCRec->fRasterClip.setEmpty(); |
| 1453 } | 1443 } |
| 1454 } | 1444 } |
| 1455 #endif | 1445 #endif |
| 1456 | 1446 |
| 1457 AutoValidateClip avc(this); | 1447 AutoValidateClip avc(this); |
| 1458 | 1448 |
| 1459 fDeviceCMDirty = true; | 1449 fDeviceCMDirty = true; |
| 1460 fCachedLocalClipBoundsDirty = true; | 1450 fCachedLocalClipBoundsDirty = true; |
| 1461 if (!fAllowSoftClip) { | 1451 if (!fAllowSoftClip) { |
| 1462 edgeStyle = kHard_ClipEdgeStyle; | 1452 edgeStyle = kHard_ClipEdgeStyle; |
| 1463 } | 1453 } |
| 1464 | 1454 |
| 1465 SkPath devPath; | 1455 SkPath devPath; |
| 1466 path.transform(*fMCRec->fMatrix, &devPath); | 1456 path.transform(fMCRec->fMatrix, &devPath); |
| 1467 | 1457 |
| 1468 // Check if the transfomation, or the original path itself | 1458 // Check if the transfomation, or the original path itself |
| 1469 // made us empty. Note this can also happen if we contained NaN | 1459 // made us empty. Note this can also happen if we contained NaN |
| 1470 // values. computing the bounds detects this, and will set our | 1460 // values. computing the bounds detects this, and will set our |
| 1471 // bounds to empty if that is the case. (see SkRect::set(pts, count)) | 1461 // bounds to empty if that is the case. (see SkRect::set(pts, count)) |
| 1472 if (devPath.getBounds().isEmpty()) { | 1462 if (devPath.getBounds().isEmpty()) { |
| 1473 // resetting the path will remove any NaN or other wanky values | 1463 // resetting the path will remove any NaN or other wanky values |
| 1474 // that might upset our scan converter. | 1464 // that might upset our scan converter. |
| 1475 devPath.reset(); | 1465 devPath.reset(); |
| 1476 } | 1466 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1499 // if the prev and curr clips disagree about aa -vs- not, favor the
aa request. | 1489 // if the prev and curr clips disagree about aa -vs- not, favor the
aa request. |
| 1500 // perhaps we need an API change to avoid this sort of mixed-signals
about | 1490 // perhaps we need an API change to avoid this sort of mixed-signals
about |
| 1501 // clipping. | 1491 // clipping. |
| 1502 if (element->isAA()) { | 1492 if (element->isAA()) { |
| 1503 edgeStyle = kSoft_ClipEdgeStyle; | 1493 edgeStyle = kSoft_ClipEdgeStyle; |
| 1504 } | 1494 } |
| 1505 } | 1495 } |
| 1506 op = SkRegion::kReplace_Op; | 1496 op = SkRegion::kReplace_Op; |
| 1507 } | 1497 } |
| 1508 | 1498 |
| 1509 clip_path_helper(this, fMCRec->fRasterClip, devPath, op, edgeStyle); | 1499 clip_path_helper(this, &fMCRec->fRasterClip, devPath, op, edgeStyle); |
| 1510 } | 1500 } |
| 1511 | 1501 |
| 1512 void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegio
n::Op op, | 1502 void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegio
n::Op op, |
| 1513 bool inverseFilled) { | 1503 bool inverseFilled) { |
| 1514 // This is for updating the clip conservatively using only bounds | 1504 // This is for updating the clip conservatively using only bounds |
| 1515 // information. | 1505 // information. |
| 1516 // Contract: | 1506 // Contract: |
| 1517 // The current clip must contain the true clip. The true | 1507 // The current clip must contain the true clip. The true |
| 1518 // clip is the clip that would have normally been computed | 1508 // clip is the clip that would have normally been computed |
| 1519 // by calls to clipPath and clipRRect | 1509 // by calls to clipPath and clipRRect |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1592 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { | 1582 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { |
| 1593 AutoValidateClip avc(this); | 1583 AutoValidateClip avc(this); |
| 1594 | 1584 |
| 1595 fDeviceCMDirty = true; | 1585 fDeviceCMDirty = true; |
| 1596 fCachedLocalClipBoundsDirty = true; | 1586 fCachedLocalClipBoundsDirty = true; |
| 1597 | 1587 |
| 1598 // todo: signal fClipStack that we have a region, and therefore (I guess) | 1588 // todo: signal fClipStack that we have a region, and therefore (I guess) |
| 1599 // we have to ignore it, and use the region directly? | 1589 // we have to ignore it, and use the region directly? |
| 1600 fClipStack.clipDevRect(rgn.getBounds(), op); | 1590 fClipStack.clipDevRect(rgn.getBounds(), op); |
| 1601 | 1591 |
| 1602 fMCRec->fRasterClip->op(rgn, op); | 1592 fMCRec->fRasterClip.op(rgn, op); |
| 1603 } | 1593 } |
| 1604 | 1594 |
| 1605 #ifdef SK_DEBUG | 1595 #ifdef SK_DEBUG |
| 1606 void SkCanvas::validateClip() const { | 1596 void SkCanvas::validateClip() const { |
| 1607 // construct clipRgn from the clipstack | 1597 // construct clipRgn from the clipstack |
| 1608 const SkBaseDevice* device = this->getDevice(); | 1598 const SkBaseDevice* device = this->getDevice(); |
| 1609 if (!device) { | 1599 if (!device) { |
| 1610 SkASSERT(this->isClipEmpty()); | 1600 SkASSERT(this->isClipEmpty()); |
| 1611 return; | 1601 return; |
| 1612 } | 1602 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1642 const SkClipStack::Element* element; | 1632 const SkClipStack::Element* element; |
| 1643 | 1633 |
| 1644 while ((element = iter.next()) != NULL) { | 1634 while ((element = iter.next()) != NULL) { |
| 1645 element->replay(visitor); | 1635 element->replay(visitor); |
| 1646 } | 1636 } |
| 1647 } | 1637 } |
| 1648 | 1638 |
| 1649 /////////////////////////////////////////////////////////////////////////////// | 1639 /////////////////////////////////////////////////////////////////////////////// |
| 1650 | 1640 |
| 1651 bool SkCanvas::isClipEmpty() const { | 1641 bool SkCanvas::isClipEmpty() const { |
| 1652 return fMCRec->fRasterClip->isEmpty(); | 1642 return fMCRec->fRasterClip.isEmpty(); |
| 1653 } | 1643 } |
| 1654 | 1644 |
| 1655 bool SkCanvas::isClipRect() const { | 1645 bool SkCanvas::isClipRect() const { |
| 1656 return fMCRec->fRasterClip->isRect(); | 1646 return fMCRec->fRasterClip.isRect(); |
| 1657 } | 1647 } |
| 1658 | 1648 |
| 1659 bool SkCanvas::quickReject(const SkRect& rect) const { | 1649 bool SkCanvas::quickReject(const SkRect& rect) const { |
| 1660 | 1650 |
| 1661 if (!rect.isFinite()) | 1651 if (!rect.isFinite()) |
| 1662 return true; | 1652 return true; |
| 1663 | 1653 |
| 1664 if (fMCRec->fRasterClip->isEmpty()) { | 1654 if (fMCRec->fRasterClip.isEmpty()) { |
| 1665 return true; | 1655 return true; |
| 1666 } | 1656 } |
| 1667 | 1657 |
| 1668 if (fMCRec->fMatrix->hasPerspective()) { | 1658 if (fMCRec->fMatrix.hasPerspective()) { |
| 1669 SkRect dst; | 1659 SkRect dst; |
| 1670 fMCRec->fMatrix->mapRect(&dst, rect); | 1660 fMCRec->fMatrix.mapRect(&dst, rect); |
| 1671 SkIRect idst; | 1661 SkIRect idst; |
| 1672 dst.roundOut(&idst); | 1662 dst.roundOut(&idst); |
| 1673 return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds()); | 1663 return !SkIRect::Intersects(idst, fMCRec->fRasterClip.getBounds()); |
| 1674 } else { | 1664 } else { |
| 1675 const SkRect& clipR = this->getLocalClipBounds(); | 1665 const SkRect& clipR = this->getLocalClipBounds(); |
| 1676 | 1666 |
| 1677 // for speed, do the most likely reject compares first | 1667 // for speed, do the most likely reject compares first |
| 1678 // TODO: should we use | instead, or compare all 4 at once? | 1668 // TODO: should we use | instead, or compare all 4 at once? |
| 1679 if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { | 1669 if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { |
| 1680 return true; | 1670 return true; |
| 1681 } | 1671 } |
| 1682 if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { | 1672 if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { |
| 1683 return true; | 1673 return true; |
| 1684 } | 1674 } |
| 1685 return false; | 1675 return false; |
| 1686 } | 1676 } |
| 1687 } | 1677 } |
| 1688 | 1678 |
| 1689 bool SkCanvas::quickReject(const SkPath& path) const { | 1679 bool SkCanvas::quickReject(const SkPath& path) const { |
| 1690 return path.isEmpty() || this->quickReject(path.getBounds()); | 1680 return path.isEmpty() || this->quickReject(path.getBounds()); |
| 1691 } | 1681 } |
| 1692 | 1682 |
| 1693 bool SkCanvas::getClipBounds(SkRect* bounds) const { | 1683 bool SkCanvas::getClipBounds(SkRect* bounds) const { |
| 1694 SkIRect ibounds; | 1684 SkIRect ibounds; |
| 1695 if (!this->getClipDeviceBounds(&ibounds)) { | 1685 if (!this->getClipDeviceBounds(&ibounds)) { |
| 1696 return false; | 1686 return false; |
| 1697 } | 1687 } |
| 1698 | 1688 |
| 1699 SkMatrix inverse; | 1689 SkMatrix inverse; |
| 1700 // if we can't invert the CTM, we can't return local clip bounds | 1690 // if we can't invert the CTM, we can't return local clip bounds |
| 1701 if (!fMCRec->fMatrix->invert(&inverse)) { | 1691 if (!fMCRec->fMatrix.invert(&inverse)) { |
| 1702 if (bounds) { | 1692 if (bounds) { |
| 1703 bounds->setEmpty(); | 1693 bounds->setEmpty(); |
| 1704 } | 1694 } |
| 1705 return false; | 1695 return false; |
| 1706 } | 1696 } |
| 1707 | 1697 |
| 1708 if (NULL != bounds) { | 1698 if (NULL != bounds) { |
| 1709 SkRect r; | 1699 SkRect r; |
| 1710 // adjust it outwards in case we are antialiasing | 1700 // adjust it outwards in case we are antialiasing |
| 1711 const int inset = 1; | 1701 const int inset = 1; |
| 1712 | 1702 |
| 1713 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, | 1703 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, |
| 1714 ibounds.fRight + inset, ibounds.fBottom + inset); | 1704 ibounds.fRight + inset, ibounds.fBottom + inset); |
| 1715 inverse.mapRect(bounds, r); | 1705 inverse.mapRect(bounds, r); |
| 1716 } | 1706 } |
| 1717 return true; | 1707 return true; |
| 1718 } | 1708 } |
| 1719 | 1709 |
| 1720 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { | 1710 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { |
| 1721 const SkRasterClip& clip = *fMCRec->fRasterClip; | 1711 const SkRasterClip& clip = fMCRec->fRasterClip; |
| 1722 if (clip.isEmpty()) { | 1712 if (clip.isEmpty()) { |
| 1723 if (bounds) { | 1713 if (bounds) { |
| 1724 bounds->setEmpty(); | 1714 bounds->setEmpty(); |
| 1725 } | 1715 } |
| 1726 return false; | 1716 return false; |
| 1727 } | 1717 } |
| 1728 | 1718 |
| 1729 if (NULL != bounds) { | 1719 if (NULL != bounds) { |
| 1730 *bounds = clip.getBounds(); | 1720 *bounds = clip.getBounds(); |
| 1731 } | 1721 } |
| 1732 return true; | 1722 return true; |
| 1733 } | 1723 } |
| 1734 | 1724 |
| 1735 const SkMatrix& SkCanvas::getTotalMatrix() const { | 1725 const SkMatrix& SkCanvas::getTotalMatrix() const { |
| 1736 return *fMCRec->fMatrix; | 1726 return fMCRec->fMatrix; |
| 1737 } | 1727 } |
| 1738 | 1728 |
| 1739 #ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE | 1729 #ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE |
| 1740 SkCanvas::ClipType SkCanvas::getClipType() const { | 1730 SkCanvas::ClipType SkCanvas::getClipType() const { |
| 1741 if (fMCRec->fRasterClip->isEmpty()) { | 1731 if (fMCRec->fRasterClip.isEmpty()) { |
| 1742 return kEmpty_ClipType; | 1732 return kEmpty_ClipType; |
| 1743 } | 1733 } |
| 1744 if (fMCRec->fRasterClip->isRect()) { | 1734 if (fMCRec->fRasterClip.isRect()) { |
| 1745 return kRect_ClipType; | 1735 return kRect_ClipType; |
| 1746 } | 1736 } |
| 1747 return kComplex_ClipType; | 1737 return kComplex_ClipType; |
| 1748 } | 1738 } |
| 1749 #endif | 1739 #endif |
| 1750 | 1740 |
| 1751 const SkRegion& SkCanvas::internal_private_getTotalClip() const { | 1741 const SkRegion& SkCanvas::internal_private_getTotalClip() const { |
| 1752 return fMCRec->fRasterClip->forceGetBW(); | 1742 return fMCRec->fRasterClip.forceGetBW(); |
| 1753 } | 1743 } |
| 1754 | 1744 |
| 1755 void SkCanvas::internal_private_getTotalClipAsPath(SkPath* path) const { | 1745 void SkCanvas::internal_private_getTotalClipAsPath(SkPath* path) const { |
| 1756 path->reset(); | 1746 path->reset(); |
| 1757 | 1747 |
| 1758 const SkRegion& rgn = fMCRec->fRasterClip->forceGetBW(); | 1748 const SkRegion& rgn = fMCRec->fRasterClip.forceGetBW(); |
| 1759 if (rgn.isEmpty()) { | 1749 if (rgn.isEmpty()) { |
| 1760 return; | 1750 return; |
| 1761 } | 1751 } |
| 1762 (void)rgn.getBoundaryPath(path); | 1752 (void)rgn.getBoundaryPath(path); |
| 1763 } | 1753 } |
| 1764 | 1754 |
| 1765 GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() { | 1755 GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() { |
| 1766 SkBaseDevice* dev = this->getTopDevice(); | 1756 SkBaseDevice* dev = this->getTopDevice(); |
| 1767 return dev ? dev->accessRenderTarget() : NULL; | 1757 return dev ? dev->accessRenderTarget() : NULL; |
| 1768 } | 1758 } |
| (...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2557 if (!supported_for_raster_canvas(info)) { | 2547 if (!supported_for_raster_canvas(info)) { |
| 2558 return NULL; | 2548 return NULL; |
| 2559 } | 2549 } |
| 2560 | 2550 |
| 2561 SkBitmap bitmap; | 2551 SkBitmap bitmap; |
| 2562 if (!bitmap.installPixels(info, pixels, rowBytes)) { | 2552 if (!bitmap.installPixels(info, pixels, rowBytes)) { |
| 2563 return NULL; | 2553 return NULL; |
| 2564 } | 2554 } |
| 2565 return SkNEW_ARGS(SkCanvas, (bitmap)); | 2555 return SkNEW_ARGS(SkCanvas, (bitmap)); |
| 2566 } | 2556 } |
| OLD | NEW |