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

Side by Side Diff: src/core/SkCanvas.cpp

Issue 1140943004: Implement support for non-scale/translate CTM in image filters. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: add comment Created 5 years, 7 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
« no previous file with comments | « include/core/SkCanvas.h ('k') | no next file » | 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 * 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 #include "SkCanvas.h" 8 #include "SkCanvas.h"
9 #include "SkCanvasPriv.h" 9 #include "SkCanvasPriv.h"
10 #include "SkBitmapDevice.h" 10 #include "SkBitmapDevice.h"
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 values: they reflect the top of the save stack, but translated and clipped 108 values: they reflect the top of the save stack, but translated and clipped
109 by the device's XY offset and bitmap-bounds. 109 by the device's XY offset and bitmap-bounds.
110 */ 110 */
111 struct DeviceCM { 111 struct DeviceCM {
112 DeviceCM* fNext; 112 DeviceCM* fNext;
113 SkBaseDevice* fDevice; 113 SkBaseDevice* fDevice;
114 SkRasterClip fClip; 114 SkRasterClip fClip;
115 SkPaint* fPaint; // may be null (in the future) 115 SkPaint* fPaint; // may be null (in the future)
116 const SkMatrix* fMatrix; 116 const SkMatrix* fMatrix;
117 SkMatrix fMatrixStorage; 117 SkMatrix fMatrixStorage;
118 SkMatrix fStashedMatrix; // Original CTM; used by imageFilter at saveLayer time
118 const bool fDeviceIsBitmapDevice; 119 const bool fDeviceIsBitmapDevice;
119 120
120 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, 121 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
121 bool conservativeRasterClip, bool deviceIsBitmapDevice) 122 bool conservativeRasterClip, bool deviceIsBitmapDevice, const SkMat rix& stashed)
122 : fNext(NULL) 123 : fNext(NULL)
123 , fClip(conservativeRasterClip) 124 , fClip(conservativeRasterClip)
125 , fStashedMatrix(stashed)
124 , fDeviceIsBitmapDevice(deviceIsBitmapDevice) 126 , fDeviceIsBitmapDevice(deviceIsBitmapDevice)
125 { 127 {
126 if (NULL != device) { 128 if (NULL != device) {
127 device->ref(); 129 device->ref();
128 device->onAttachToCanvas(canvas); 130 device->onAttachToCanvas(canvas);
129 } 131 }
130 fDevice = device; 132 fDevice = device;
131 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 133 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
132 } 134 }
133 135
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 fSaveCount = 1; 523 fSaveCount = 1;
522 fMetaData = NULL; 524 fMetaData = NULL;
523 525
524 fClipStack.reset(SkNEW(SkClipStack)); 526 fClipStack.reset(SkNEW(SkClipStack));
525 527
526 fMCRec = (MCRec*)fMCStack.push_back(); 528 fMCRec = (MCRec*)fMCStack.push_back();
527 new (fMCRec) MCRec(fConservativeRasterClip); 529 new (fMCRec) MCRec(fConservativeRasterClip);
528 530
529 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); 531 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
530 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage; 532 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
531 new (fDeviceCMStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, f alse); 533 new (fDeviceCMStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, f alse,
534 fMCRec->fMatrix);
532 535
533 fMCRec->fTopLayer = fMCRec->fLayer; 536 fMCRec->fTopLayer = fMCRec->fLayer;
534 537
535 fSurfaceBase = NULL; 538 fSurfaceBase = NULL;
536 539
537 if (device) { 540 if (device) {
538 device->initForRootLayer(fProps.pixelGeometry()); 541 device->initForRootLayer(fProps.pixelGeometry());
539 if (device->forceConservativeRasterClip()) { 542 if (device->forceConservativeRasterClip()) {
540 fConservativeRasterClip = true; 543 fConservativeRasterClip = true;
541 } 544 }
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 fSaveCount += 1; 987 fSaveCount += 1;
985 this->internalSaveLayer(bounds, paint, flags, strategy); 988 this->internalSaveLayer(bounds, paint, flags, strategy);
986 return this->getSaveCount() - 1; 989 return this->getSaveCount() - 1;
987 } 990 }
988 991
989 void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav eFlags flags, 992 void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav eFlags flags,
990 SaveLayerStrategy strategy) { 993 SaveLayerStrategy strategy) {
991 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 994 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
992 flags |= kClipToLayer_SaveFlag; 995 flags |= kClipToLayer_SaveFlag;
993 #endif 996 #endif
997 SkLazyPaint lazyP;
998 SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL;
999 SkMatrix stashedMatrix = fMCRec->fMatrix;
1000 #ifndef SK_SUPPORT_LEGACY_IMAGEFILTER_CTM
1001 SkMatrix remainder;
1002 SkSize scale;
1003 /*
1004 * ImageFilters (so far) do not correctly handle matrices (CTM) that contai n rotation/skew/etc.
1005 * but they do handle scaling. To accommodate this, we do the following:
1006 *
1007 * 1. Stash off the current CTM
1008 * 2. Decompose the CTM into SCALE and REMAINDER
1009 * 3. Wack the CTM to be just SCALE, and wrap the imagefilter with a Matrix ImageFilter that
1010 * contains the REMAINDER
1011 * 4. Proceed as usual, allowing the client to draw into the layer (now wit h a scale-only CTM)
1012 * 5. During restore, we process the MatrixImageFilter, which applies REMAI NDER to the output
1013 * of the original imagefilter, and draw that (via drawSprite)
1014 * 6. Unwack the CTM to its original state (i.e. stashedMatrix)
1015 *
1016 * Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
1017 * a sprite operation) to avoid the extra buffer/overhead of MatrixImageFil ter.
1018 */
1019 if (imageFilter &&
1020 !stashedMatrix.isScaleTranslate() && stashedMatrix.decomposeScale(&scale , &remainder)) {
1021 // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
1022 this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height( )));
1023 SkAutoTUnref<SkImageFilter> matrixFilter(SkImageFilter::CreateMatrixFilt er(
1024 remainder, SkFilterQuality::kLow_SkFilterQua lity, imageFilter));
1025 imageFilter = matrixFilter.get();
1026 SkPaint* p = lazyP.set(*paint);
1027 p->setImageFilter(imageFilter);
1028 paint = p;
1029 }
1030 #endif
994 1031
995 // do this before we create the layer. We don't call the public save() since 1032 // do this before we create the layer. We don't call the public save() since
996 // that would invoke a possibly overridden virtual 1033 // that would invoke a possibly overridden virtual
997 this->internalSave(); 1034 this->internalSave();
998 1035
999 fDeviceCMDirty = true; 1036 fDeviceCMDirty = true;
1000 1037
1001 SkIRect ir; 1038 SkIRect ir;
1002 if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter( ) : NULL)) { 1039 if (!this->clipRectBounds(bounds, flags, &ir, imageFilter)) {
1003 return; 1040 return;
1004 } 1041 }
1005 1042
1006 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about 1043 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1007 // the clipRectBounds() call above? 1044 // the clipRectBounds() call above?
1008 if (kNoLayer_SaveLayerStrategy == strategy) { 1045 if (kNoLayer_SaveLayerStrategy == strategy) {
1009 return; 1046 return;
1010 } 1047 }
1011 1048
1012 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); 1049 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
(...skipping 27 matching lines...) Expand all
1040 "Unable to create device for layer.") ; 1077 "Unable to create device for layer.") ;
1041 return; 1078 return;
1042 } 1079 }
1043 forceSpriteOnRestore = true; 1080 forceSpriteOnRestore = true;
1044 } 1081 }
1045 device = newDev; 1082 device = newDev;
1046 } 1083 }
1047 1084
1048 device->setOrigin(ir.fLeft, ir.fTop); 1085 device->setOrigin(ir.fLeft, ir.fTop);
1049 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRa sterClip, 1086 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRa sterClip,
1050 forceSpriteOnRestore)); 1087 forceSpriteOnRestore, stashedMatrix) );
1051 device->unref(); 1088 device->unref();
1052 1089
1053 layer->fNext = fMCRec->fTopLayer; 1090 layer->fNext = fMCRec->fTopLayer;
1054 fMCRec->fLayer = layer; 1091 fMCRec->fLayer = layer;
1055 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 1092 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer
1056 } 1093 }
1057 1094
1058 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { 1095 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1059 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag); 1096 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
1060 } 1097 }
(...skipping 29 matching lines...) Expand all
1090 1127
1091 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 1128 /* Time to draw the layer's offscreen. We can't call the public drawSprite,
1092 since if we're being recorded, we don't want to record this (the 1129 since if we're being recorded, we don't want to record this (the
1093 recorder will have already recorded the restore). 1130 recorder will have already recorded the restore).
1094 */ 1131 */
1095 if (layer) { 1132 if (layer) {
1096 if (layer->fNext) { 1133 if (layer->fNext) {
1097 const SkIPoint& origin = layer->fDevice->getOrigin(); 1134 const SkIPoint& origin = layer->fDevice->getOrigin();
1098 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 1135 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
1099 layer->fPaint, layer->fDeviceIsBitmapDevice ); 1136 layer->fPaint, layer->fDeviceIsBitmapDevice );
1137 // restore what we smashed in internalSaveLayer
1138 fMCRec->fMatrix = layer->fStashedMatrix;
1100 // reset this, since internalDrawDevice will have set it to true 1139 // reset this, since internalDrawDevice will have set it to true
1101 fDeviceCMDirty = true; 1140 fDeviceCMDirty = true;
1102 SkDELETE(layer); 1141 SkDELETE(layer);
1103 } else { 1142 } else {
1104 // we're at the root 1143 // we're at the root
1105 SkASSERT(layer == (void*)fDeviceCMStorage); 1144 SkASSERT(layer == (void*)fDeviceCMStorage);
1106 layer->~DeviceCM(); 1145 layer->~DeviceCM();
1146 // no need to update fMCRec, 'cause we're killing the canvas
1107 } 1147 }
1108 } 1148 }
1109 } 1149 }
1110 1150
1111 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p rops) { 1151 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p rops) {
1112 if (NULL == props) { 1152 if (NULL == props) {
1113 props = &fProps; 1153 props = &fProps;
1114 } 1154 }
1115 return this->onNewSurface(info, *props); 1155 return this->onNewSurface(info, *props);
1116 } 1156 }
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
1325 } 1365 }
1326 1366
1327 this->checkForDeferredSave(); 1367 this->checkForDeferredSave();
1328 fDeviceCMDirty = true; 1368 fDeviceCMDirty = true;
1329 fCachedLocalClipBoundsDirty = true; 1369 fCachedLocalClipBoundsDirty = true;
1330 fMCRec->fMatrix.preConcat(matrix); 1370 fMCRec->fMatrix.preConcat(matrix);
1331 1371
1332 this->didConcat(matrix); 1372 this->didConcat(matrix);
1333 } 1373 }
1334 1374
1375 void SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
1376 fDeviceCMDirty = true;
1377 fCachedLocalClipBoundsDirty = true;
1378 fMCRec->fMatrix = matrix;
1379 }
1380
1335 void SkCanvas::setMatrix(const SkMatrix& matrix) { 1381 void SkCanvas::setMatrix(const SkMatrix& matrix) {
1336 this->checkForDeferredSave(); 1382 this->checkForDeferredSave();
1337 fDeviceCMDirty = true; 1383 this->internalSetMatrix(matrix);
1338 fCachedLocalClipBoundsDirty = true;
1339 fMCRec->fMatrix = matrix;
1340 this->didSetMatrix(matrix); 1384 this->didSetMatrix(matrix);
1341 } 1385 }
1342 1386
1343 void SkCanvas::resetMatrix() { 1387 void SkCanvas::resetMatrix() {
1344 SkMatrix matrix; 1388 SkMatrix matrix;
1345 1389
1346 matrix.reset(); 1390 matrix.reset();
1347 this->setMatrix(matrix); 1391 this->setMatrix(matrix);
1348 } 1392 }
1349 1393
(...skipping 1337 matching lines...) Expand 10 before | Expand all | Expand 10 after
2687 } 2731 }
2688 2732
2689 if (matrix) { 2733 if (matrix) {
2690 canvas->concat(*matrix); 2734 canvas->concat(*matrix);
2691 } 2735 }
2692 } 2736 }
2693 2737
2694 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 2738 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2695 fCanvas->restoreToCount(fSaveCount); 2739 fCanvas->restoreToCount(fSaveCount);
2696 } 2740 }
OLDNEW
« no previous file with comments | « include/core/SkCanvas.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698