SkCanvasStack.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * Copyright 2013 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/utils/SkCanvasStack.h"
  8. SkCanvasStack::SkCanvasStack(int width, int height)
  9. : INHERITED(width, height) {}
  10. SkCanvasStack::~SkCanvasStack() {
  11. this->removeAll();
  12. }
  13. void SkCanvasStack::pushCanvas(std::unique_ptr<SkCanvas> canvas, const SkIPoint& origin) {
  14. if (canvas) {
  15. // compute the bounds of this canvas
  16. const SkIRect canvasBounds = SkIRect::MakeSize(canvas->getBaseLayerSize());
  17. // push the canvas onto the stack
  18. this->INHERITED::addCanvas(canvas.get());
  19. // push the canvas data onto the stack
  20. CanvasData* data = &fCanvasData.push_back();
  21. data->origin = origin;
  22. data->requiredClip.setRect(canvasBounds);
  23. data->ownedCanvas = std::move(canvas);
  24. // subtract this region from the canvas objects already on the stack.
  25. // This ensures they do not draw into the space occupied by the layers
  26. // above them.
  27. for (int i = fList.count() - 1; i > 0; --i) {
  28. SkIRect localBounds = canvasBounds;
  29. localBounds.offset(origin - fCanvasData[i-1].origin);
  30. fCanvasData[i-1].requiredClip.op(localBounds, SkRegion::kDifference_Op);
  31. fList[i-1]->clipRegion(fCanvasData[i-1].requiredClip);
  32. }
  33. }
  34. SkASSERT(fList.count() == fCanvasData.count());
  35. }
  36. void SkCanvasStack::removeAll() {
  37. this->INHERITED::removeAll(); // call the baseclass *before* we actually delete the canvases
  38. fCanvasData.reset();
  39. }
  40. /**
  41. * Traverse all canvases (e.g. layers) the stack and ensure that they are clipped
  42. * to their bounds and that the area covered by any canvas higher in the stack is
  43. * also clipped out.
  44. */
  45. void SkCanvasStack::clipToZOrderedBounds() {
  46. SkASSERT(fList.count() == fCanvasData.count());
  47. for (int i = 0; i < fList.count(); ++i) {
  48. fList[i]->clipRegion(fCanvasData[i].requiredClip);
  49. }
  50. }
  51. ////////////////////////////////////////////////////////////////////////////////
  52. /**
  53. * We need to handle setMatrix specially as it overwrites the matrix in each
  54. * canvas unlike all other matrix operations (i.e. translate, scale, etc) which
  55. * just pre-concatenate with the existing matrix.
  56. */
  57. void SkCanvasStack::didSetMatrix(const SkMatrix& matrix) {
  58. SkASSERT(fList.count() == fCanvasData.count());
  59. for (int i = 0; i < fList.count(); ++i) {
  60. SkMatrix tempMatrix = matrix;
  61. tempMatrix.postTranslate(SkIntToScalar(-fCanvasData[i].origin.x()),
  62. SkIntToScalar(-fCanvasData[i].origin.y()));
  63. fList[i]->setMatrix(tempMatrix);
  64. }
  65. this->SkCanvas::didSetMatrix(matrix);
  66. }
  67. void SkCanvasStack::onClipRect(const SkRect& r, SkClipOp op, ClipEdgeStyle edgeStyle) {
  68. this->INHERITED::onClipRect(r, op, edgeStyle);
  69. this->clipToZOrderedBounds();
  70. }
  71. void SkCanvasStack::onClipRRect(const SkRRect& rr, SkClipOp op, ClipEdgeStyle edgeStyle) {
  72. this->INHERITED::onClipRRect(rr, op, edgeStyle);
  73. this->clipToZOrderedBounds();
  74. }
  75. void SkCanvasStack::onClipPath(const SkPath& p, SkClipOp op, ClipEdgeStyle edgeStyle) {
  76. this->INHERITED::onClipPath(p, op, edgeStyle);
  77. this->clipToZOrderedBounds();
  78. }
  79. void SkCanvasStack::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) {
  80. SkASSERT(fList.count() == fCanvasData.count());
  81. for (int i = 0; i < fList.count(); ++i) {
  82. SkRegion tempRegion;
  83. deviceRgn.translate(-fCanvasData[i].origin.x(),
  84. -fCanvasData[i].origin.y(), &tempRegion);
  85. tempRegion.op(fCanvasData[i].requiredClip, SkRegion::kIntersect_Op);
  86. fList[i]->clipRegion(tempRegion, op);
  87. }
  88. this->SkCanvas::onClipRegion(deviceRgn, op);
  89. }