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

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

Issue 1899263002: post apply non-scale transforms after imagefilters have run (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fission out gm to separate pre-CL Created 4 years, 8 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
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 "SkBitmapDevice.h" 8 #include "SkBitmapDevice.h"
9 #include "SkCanvas.h" 9 #include "SkCanvas.h"
10 #include "SkCanvasPriv.h" 10 #include "SkCanvasPriv.h"
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 values: they reflect the top of the save stack, but translated and clipped 189 values: they reflect the top of the save stack, but translated and clipped
190 by the device's XY offset and bitmap-bounds. 190 by the device's XY offset and bitmap-bounds.
191 */ 191 */
192 struct DeviceCM { 192 struct DeviceCM {
193 DeviceCM* fNext; 193 DeviceCM* fNext;
194 SkBaseDevice* fDevice; 194 SkBaseDevice* fDevice;
195 SkRasterClip fClip; 195 SkRasterClip fClip;
196 SkPaint* fPaint; // may be null (in the future) 196 SkPaint* fPaint; // may be null (in the future)
197 const SkMatrix* fMatrix; 197 const SkMatrix* fMatrix;
198 SkMatrix fMatrixStorage; 198 SkMatrix fMatrixStorage;
199 SkMatrix fStashedMatrix; // original CTM; used by imagefilter in saveLayer
199 const bool fDeviceIsBitmapDevice; 200 const bool fDeviceIsBitmapDevice;
200 201
201 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, 202 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas,
202 bool conservativeRasterClip, bool deviceIsBitmapDevice) 203 bool conservativeRasterClip, bool deviceIsBitmapDevice, const SkMat rix& stashed)
203 : fNext(nullptr) 204 : fNext(nullptr)
204 , fClip(conservativeRasterClip) 205 , fClip(conservativeRasterClip)
206 , fStashedMatrix(stashed)
205 , fDeviceIsBitmapDevice(deviceIsBitmapDevice) 207 , fDeviceIsBitmapDevice(deviceIsBitmapDevice)
206 { 208 {
207 if (nullptr != device) { 209 if (nullptr != device) {
208 device->ref(); 210 device->ref();
209 device->onAttachToCanvas(canvas); 211 device->onAttachToCanvas(canvas);
210 } 212 }
211 fDevice = device; 213 fDevice = device;
212 fPaint = paint ? new SkPaint(*paint) : nullptr; 214 fPaint = paint ? new SkPaint(*paint) : nullptr;
213 } 215 }
214 216
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 */ 483 */
482 SkPaint tmp; 484 SkPaint tmp;
483 tmp.setImageFilter(fPaint->getImageFilter()); 485 tmp.setImageFilter(fPaint->getImageFilter());
484 tmp.setXfermode(sk_ref_sp(fPaint->getXfermode())); 486 tmp.setXfermode(sk_ref_sp(fPaint->getXfermode()));
485 SkRect storage; 487 SkRect storage;
486 if (rawBounds) { 488 if (rawBounds) {
487 // Make rawBounds include all paint outsets except for those due to image filters. 489 // Make rawBounds include all paint outsets except for those due to image filters.
488 rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *ra wBounds, &storage); 490 rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *ra wBounds, &storage);
489 } 491 }
490 (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &t mp), 492 (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &t mp),
491 SkCanvas::kFullLayer_SaveLayerStrate gy); 493 SkCanvas::kFullLayer_SaveLayerStrate gy,
494 fPaint->isAntiAlias());
492 fTempLayerForImageFilter = true; 495 fTempLayerForImageFilter = true;
493 // we remove the imagefilter/xfermode inside doNext() 496 // we remove the imagefilter/xfermode inside doNext()
494 } 497 }
495 498
496 if (SkDrawLooper* looper = paint.getLooper()) { 499 if (SkDrawLooper* looper = paint.getLooper()) {
497 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Contex t>( 500 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Contex t>(
498 looper->contextSize()); 501 looper->contextSize());
499 fLooperContext = looper->createContext(canvas, buffer); 502 fLooperContext = looper->createContext(canvas, buffer);
500 fIsSimple = false; 503 fIsSimple = false;
501 } else { 504 } else {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 fSaveCount = 1; 660 fSaveCount = 1;
658 fMetaData = nullptr; 661 fMetaData = nullptr;
659 662
660 fClipStack.reset(new SkClipStack); 663 fClipStack.reset(new SkClipStack);
661 664
662 fMCRec = (MCRec*)fMCStack.push_back(); 665 fMCRec = (MCRec*)fMCStack.push_back();
663 new (fMCRec) MCRec(fConservativeRasterClip); 666 new (fMCRec) MCRec(fConservativeRasterClip);
664 667
665 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); 668 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
666 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage; 669 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
667 new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRast erClip, false); 670 new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRast erClip, false,
671 fMCRec->fMatrix);
668 672
669 fMCRec->fTopLayer = fMCRec->fLayer; 673 fMCRec->fTopLayer = fMCRec->fLayer;
670 674
671 fSurfaceBase = nullptr; 675 fSurfaceBase = nullptr;
672 676
673 if (device) { 677 if (device) {
674 // The root device and the canvas should always have the same pixel geom etry 678 // The root device and the canvas should always have the same pixel geom etry
675 SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry( )); 679 SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry( ));
676 device->onAttachToCanvas(this); 680 device->onAttachToCanvas(this);
677 fMCRec->fLayer->fDevice = SkRef(device); 681 fMCRec->fLayer->fDevice = SkRef(device);
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType ; 1181 SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType ;
1178 if ((prev.bytesPerPixel() < 4) || hasImageFilter) { 1182 if ((prev.bytesPerPixel() < 4) || hasImageFilter) {
1179 // force to L32 1183 // force to L32
1180 return SkImageInfo::MakeN32(w, h, alphaType); 1184 return SkImageInfo::MakeN32(w, h, alphaType);
1181 } else { 1185 } else {
1182 // keep the same characteristics as the prev 1186 // keep the same characteristics as the prev
1183 return SkImageInfo::Make(w, h, prev.colorType(), alphaType, prev.profile Type()); 1187 return SkImageInfo::Make(w, h, prev.colorType(), alphaType, prev.profile Type());
1184 } 1188 }
1185 } 1189 }
1186 1190
1187 void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra tegy) { 1191 void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra tegy,
1192 bool doAAInMatrixFilter) {
1188 const SkRect* bounds = rec.fBounds; 1193 const SkRect* bounds = rec.fBounds;
1189 const SkPaint* paint = rec.fPaint; 1194 const SkPaint* paint = rec.fPaint;
1190 SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags; 1195 SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
1191 1196
1192 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 1197 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
1193 saveLayerFlags &= ~kDontClipToLayer_PrivateSaveLayerFlag; 1198 saveLayerFlags &= ~kDontClipToLayer_PrivateSaveLayerFlag;
1194 #endif 1199 #endif
1195 1200
1201 SkLazyPaint lazyP;
1202 SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL;
1203 SkMatrix stashedMatrix = fMCRec->fMatrix;
1204 #ifndef SK_SUPPORT_LEGACY_IMAGEFILTER_CTM
1205 SkMatrix remainder;
1206 SkSize scale;
1207 /*
1208 * ImageFilters (so far) do not correctly handle matrices (CTM) that contai n rotation/skew/etc.
1209 * but they do handle scaling. To accommodate this, we do the following:
1210 *
1211 * 1. Stash off the current CTM
1212 * 2. Decompose the CTM into SCALE and REMAINDER
1213 * 3. Wack the CTM to be just SCALE, and wrap the imagefilter with a Matrix ImageFilter that
1214 * contains the REMAINDER
1215 * 4. Proceed as usual, allowing the client to draw into the layer (now wit h a scale-only CTM)
1216 * 5. During restore, we process the MatrixImageFilter, which applies REMAI NDER to the output
1217 * of the original imagefilter, and draw that (via drawSprite)
1218 * 6. Unwack the CTM to its original state (i.e. stashedMatrix)
1219 *
1220 * Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
1221 * a sprite operation) to avoid the extra buffer/overhead of MatrixImageFil ter.
1222 */
1223 if (imageFilter &&
1224 !stashedMatrix.isScaleTranslate() &&
1225 stashedMatrix.decomposeScale(&scale, &remainder))
1226 {
1227 // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
1228 this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height( )));
1229 SkPaint* p = lazyP.set(*paint);
1230 p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
1231 SkFilterQuality::kLow_ SkFilterQuality,
1232 doAAInMatrixFilter,
1233 sk_ref_sp(imageFilter) ));
1234 imageFilter = p->getImageFilter();
1235 paint = p;
1236 }
1237 #endif
1238
1196 // do this before we create the layer. We don't call the public save() since 1239 // do this before we create the layer. We don't call the public save() since
1197 // that would invoke a possibly overridden virtual 1240 // that would invoke a possibly overridden virtual
1198 this->internalSave(); 1241 this->internalSave();
1199 1242
1200 fDeviceCMDirty = true; 1243 fDeviceCMDirty = true;
1201 1244
1202 SkIRect ir; 1245 SkIRect ir;
1203 if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, paint ? paint->getIma geFilter() : nullptr)) { 1246 if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
1204 return; 1247 return;
1205 } 1248 }
1206 1249
1207 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about 1250 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1208 // the clipRectBounds() call above? 1251 // the clipRectBounds() call above?
1209 if (kNoLayer_SaveLayerStrategy == strategy) { 1252 if (kNoLayer_SaveLayerStrategy == strategy) {
1210 return; 1253 return;
1211 } 1254 }
1212 1255
1213 bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag); 1256 bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1249 forceSpriteOnRestore = true; 1292 forceSpriteOnRestore = true;
1250 } 1293 }
1251 device = newDev; 1294 device = newDev;
1252 } 1295 }
1253 device->setOrigin(ir.fLeft, ir.fTop); 1296 device->setOrigin(ir.fLeft, ir.fTop);
1254 1297
1255 if (rec.fBackdrop) { 1298 if (rec.fBackdrop) {
1256 draw_filter_into_device(fMCRec->fTopLayer->fDevice, rec.fBackdrop, devic e, fMCRec->fMatrix); 1299 draw_filter_into_device(fMCRec->fTopLayer->fDevice, rec.fBackdrop, devic e, fMCRec->fMatrix);
1257 } 1300 }
1258 1301
1259 DeviceCM* layer = 1302 DeviceCM* layer = new DeviceCM(device, paint, this, fConservativeRasterClip,
1260 new DeviceCM(device, paint, this, fConservativeRasterClip, forceSpri teOnRestore); 1303 forceSpriteOnRestore, stashedMatrix);
1261 device->unref(); 1304 device->unref();
1262 1305
1263 layer->fNext = fMCRec->fTopLayer; 1306 layer->fNext = fMCRec->fTopLayer;
1264 fMCRec->fLayer = layer; 1307 fMCRec->fLayer = layer;
1265 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 1308 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer
1266 } 1309 }
1267 1310
1268 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { 1311 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1269 if (0xFF == alpha) { 1312 if (0xFF == alpha) {
1270 return this->saveLayer(bounds, nullptr); 1313 return this->saveLayer(bounds, nullptr);
(...skipping 24 matching lines...) Expand all
1295 1338
1296 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 1339 /* Time to draw the layer's offscreen. We can't call the public drawSprite,
1297 since if we're being recorded, we don't want to record this (the 1340 since if we're being recorded, we don't want to record this (the
1298 recorder will have already recorded the restore). 1341 recorder will have already recorded the restore).
1299 */ 1342 */
1300 if (layer) { 1343 if (layer) {
1301 if (layer->fNext) { 1344 if (layer->fNext) {
1302 const SkIPoint& origin = layer->fDevice->getOrigin(); 1345 const SkIPoint& origin = layer->fDevice->getOrigin();
1303 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 1346 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
1304 layer->fPaint, layer->fDeviceIsBitmapDevice ); 1347 layer->fPaint, layer->fDeviceIsBitmapDevice );
1348 // restore what we smashed in internalSaveLayer
1349 fMCRec->fMatrix = layer->fStashedMatrix;
1305 // reset this, since internalDrawDevice will have set it to true 1350 // reset this, since internalDrawDevice will have set it to true
1306 fDeviceCMDirty = true; 1351 fDeviceCMDirty = true;
1307 delete layer; 1352 delete layer;
1308 } else { 1353 } else {
1309 // we're at the root 1354 // we're at the root
1310 SkASSERT(layer == (void*)fDeviceCMStorage); 1355 SkASSERT(layer == (void*)fDeviceCMStorage);
1311 layer->~DeviceCM(); 1356 layer->~DeviceCM();
1357 // no need to update fMCRec, 'cause we're killing the canvas
1312 } 1358 }
1313 } 1359 }
1314 } 1360 }
1315 1361
1316 sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceP rops* props) { 1362 sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceP rops* props) {
1317 if (nullptr == props) { 1363 if (nullptr == props) {
1318 props = &fProps; 1364 props = &fProps;
1319 } 1365 }
1320 return this->onNewSurface(info, *props); 1366 return this->onNewSurface(info, *props);
1321 } 1367 }
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 } 1523 }
1478 1524
1479 this->checkForDeferredSave(); 1525 this->checkForDeferredSave();
1480 fDeviceCMDirty = true; 1526 fDeviceCMDirty = true;
1481 fCachedLocalClipBoundsDirty = true; 1527 fCachedLocalClipBoundsDirty = true;
1482 fMCRec->fMatrix.preConcat(matrix); 1528 fMCRec->fMatrix.preConcat(matrix);
1483 1529
1484 this->didConcat(matrix); 1530 this->didConcat(matrix);
1485 } 1531 }
1486 1532
1533 void SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
1534 fDeviceCMDirty = true;
1535 fCachedLocalClipBoundsDirty = true;
1536 fMCRec->fMatrix = matrix;
1537 }
1538
1487 void SkCanvas::setMatrix(const SkMatrix& matrix) { 1539 void SkCanvas::setMatrix(const SkMatrix& matrix) {
1488 this->checkForDeferredSave(); 1540 this->checkForDeferredSave();
1489 fDeviceCMDirty = true; 1541 this->internalSetMatrix(matrix);
1490 fCachedLocalClipBoundsDirty = true;
1491 fMCRec->fMatrix = matrix;
1492 this->didSetMatrix(matrix); 1542 this->didSetMatrix(matrix);
1493 } 1543 }
1494 1544
1495 void SkCanvas::resetMatrix() { 1545 void SkCanvas::resetMatrix() {
1496 SkMatrix matrix; 1546 this->setMatrix(SkMatrix::I());
1497
1498 matrix.reset();
1499 this->setMatrix(matrix);
1500 } 1547 }
1501 1548
1502 ////////////////////////////////////////////////////////////////////////////// 1549 //////////////////////////////////////////////////////////////////////////////
1503 1550
1504 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1551 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1505 this->checkForDeferredSave(); 1552 this->checkForDeferredSave();
1506 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1553 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1507 this->onClipRect(rect, op, edgeStyle); 1554 this->onClipRect(rect, op, edgeStyle);
1508 } 1555 }
1509 1556
(...skipping 1543 matching lines...) Expand 10 before | Expand all | Expand 10 after
3053 3100
3054 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 3101 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
3055 fCanvas->restoreToCount(fSaveCount); 3102 fCanvas->restoreToCount(fSaveCount);
3056 } 3103 }
3057 3104
3058 #ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API 3105 #ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API
3059 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p rops) { 3106 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p rops) {
3060 return this->makeSurface(info, props).release(); 3107 return this->makeSurface(info, props).release();
3061 } 3108 }
3062 #endif 3109 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698