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 |