| Index: src/core/SkCanvas.cpp
|
| diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
|
| index 11dc739f4c4dc6aa0509f8ba404a56fa246817e4..f9eb0ebbfef45e2823a9bb91443fa18b60fcd5e3 100644
|
| --- a/src/core/SkCanvas.cpp
|
| +++ b/src/core/SkCanvas.cpp
|
| @@ -113,11 +113,16 @@ struct DeviceCM {
|
| SkRasterClip fClip;
|
| const SkMatrix* fMatrix;
|
| SkPaint* fPaint; // may be null (in the future)
|
| + SkMatrix fStashedMatrix;
|
| + SkMatrix fExtraMatrix;
|
|
|
| DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
|
| - bool conservativeRasterClip)
|
| + bool conservativeRasterClip, const SkMatrix& stashedMatrix,
|
| + const SkMatrix& extraMatrix)
|
| : fNext(NULL)
|
| , fClip(conservativeRasterClip)
|
| + , fStashedMatrix(stashedMatrix)
|
| + , fExtraMatrix(extraMatrix)
|
| {
|
| if (NULL != device) {
|
| device->ref();
|
| @@ -438,7 +443,7 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
|
| fMCRec = (MCRec*)fMCStack.push_back();
|
| new (fMCRec) MCRec(fConservativeRasterClip);
|
|
|
| - fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, NULL, NULL, fConservativeRasterClip));
|
| + fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, NULL, NULL, fConservativeRasterClip, fMCRec->fMatrix, SkMatrix::I()));
|
| fMCRec->fTopLayer = fMCRec->fLayer;
|
|
|
| fSurfaceBase = NULL;
|
| @@ -831,7 +836,8 @@ static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
|
| }
|
|
|
| bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
|
| - SkIRect* intersection, const SkImageFilter* imageFilter) {
|
| + SkIRect* intersection, const SkImageFilter* imageFilter,
|
| + const SkMatrix* shearAndRotateMatrix) {
|
| SkIRect clipBounds;
|
| if (!this->getClipDeviceBounds(&clipBounds)) {
|
| return false;
|
| @@ -840,8 +846,24 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
|
| const SkMatrix& ctm = fMCRec->fMatrix; // this->getTotalMatrix()
|
|
|
| if (imageFilter) {
|
| + if (shearAndRotateMatrix) {
|
| + SkMatrix shearAndRotateInverse;
|
| + if (!shearAndRotateMatrix->invert(&shearAndRotateInverse)) {
|
| + return false;
|
| + }
|
| + SkMatrix matrix;
|
| + if (!ctm.invert(&matrix)) {
|
| + return false;
|
| + }
|
| + matrix.postConcat(shearAndRotateInverse);
|
| + matrix.postConcat(ctm);
|
| + SkRect floatBounds;
|
| + matrix.mapRect(&floatBounds, SkRect::Make(clipBounds));
|
| + clipBounds = floatBounds.roundOut();
|
| + }
|
| imageFilter->filterBounds(clipBounds, ctm, &clipBounds);
|
| }
|
| +
|
| SkIRect ir;
|
| if (bounds) {
|
| SkRect r;
|
| @@ -899,6 +921,23 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
|
| #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
|
| flags |= kClipToLayer_SaveFlag;
|
| #endif
|
| + SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL;
|
| + SkMatrix matrix = fMCRec->fMatrix;
|
| + SkMatrix shearAndRotate = SkMatrix::I();
|
| + bool doShearAndRotate = false;
|
| + if (imageFilter && !matrix.isScaleTranslate()) {
|
| + doShearAndRotate = true;
|
| + SkMatrix scaleAndTranslate;
|
| + scaleAndTranslate.setTranslate(matrix.getTranslateX(), matrix.getTranslateY());
|
| + SkScalar xScale = SkScalarSqrt(matrix[0] * matrix[0] + matrix[3] * matrix[3]);
|
| + SkScalar yScale = SkScalarSqrt(matrix[1] * matrix[1] + matrix[4] * matrix[4]);
|
| + scaleAndTranslate.postScale(xScale, yScale);
|
| + if (!scaleAndTranslate.invert(&shearAndRotate)) {
|
| + SkASSERT(false);
|
| + }
|
| + shearAndRotate.preConcat(matrix);
|
| + fMCRec->fMatrix = scaleAndTranslate;
|
| + }
|
|
|
| // do this before we create the layer. We don't call the public save() since
|
| // that would invoke a possibly overridden virtual
|
| @@ -907,7 +946,7 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
|
| fDeviceCMDirty = true;
|
|
|
| SkIRect ir;
|
| - if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
|
| + if (!this->clipRectBounds(bounds, flags, &ir, imageFilter, doShearAndRotate ? &shearAndRotate : NULL)) {
|
| return;
|
| }
|
|
|
| @@ -951,7 +990,7 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
|
| }
|
|
|
| device->setOrigin(ir.fLeft, ir.fTop);
|
| - DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip));
|
| + DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip, matrix, shearAndRotate));
|
| device->unref();
|
|
|
| layer->fNext = fMCRec->fTopLayer;
|
| @@ -1000,10 +1039,13 @@ void SkCanvas::internalRestore() {
|
| if (layer->fNext) {
|
| const SkIPoint& origin = layer->fDevice->getOrigin();
|
| this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
|
| - layer->fPaint);
|
| + layer->fPaint, layer->fExtraMatrix);
|
| // reset this, since internalDrawDevice will have set it to true
|
| fDeviceCMDirty = true;
|
| }
|
| + if (layer->fPaint && layer->fPaint->fImageFilter) {
|
| + fMCRec->fMatrix = layer->fStashedMatrix;
|
| + }
|
| SkDELETE(layer);
|
| }
|
| }
|
| @@ -1108,7 +1150,7 @@ void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
|
| }
|
|
|
| void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
|
| - const SkPaint* paint) {
|
| + const SkPaint* paint, const SkMatrix& extraMatrix) {
|
| SkPaint tmp;
|
| if (NULL == paint) {
|
| paint = &tmp;
|
| @@ -1133,8 +1175,16 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
|
| if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
|
| SkPaint tmpUnfiltered(*paint);
|
| tmpUnfiltered.setImageFilter(NULL);
|
| - dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
|
| - tmpUnfiltered);
|
| + if (extraMatrix.isIdentity()) {
|
| + offset += pos;
|
| + dstDev->drawSprite(iter, dst, offset.x(), offset.y(),
|
| + tmpUnfiltered);
|
| + } else {
|
| + SkMatrix matrix = extraMatrix;
|
| + matrix.preTranslate(offset.x(), offset.y());
|
| + dstDev->drawBitmap(iter, dst, matrix,
|
| + tmpUnfiltered);
|
| + }
|
| }
|
| } else {
|
| dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
|
|
|