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 #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 Loading... | |
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 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
657 fSaveCount = 1; | 659 fSaveCount = 1; |
658 fMetaData = nullptr; | 660 fMetaData = nullptr; |
659 | 661 |
660 fClipStack.reset(new SkClipStack); | 662 fClipStack.reset(new SkClipStack); |
661 | 663 |
662 fMCRec = (MCRec*)fMCStack.push_back(); | 664 fMCRec = (MCRec*)fMCStack.push_back(); |
663 new (fMCRec) MCRec(fConservativeRasterClip); | 665 new (fMCRec) MCRec(fConservativeRasterClip); |
664 | 666 |
665 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); | 667 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); |
666 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage; | 668 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage; |
667 new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRast erClip, false); | 669 new (fDeviceCMStorage) DeviceCM(nullptr, nullptr, nullptr, fConservativeRast erClip, false, |
670 fMCRec->fMatrix); | |
668 | 671 |
669 fMCRec->fTopLayer = fMCRec->fLayer; | 672 fMCRec->fTopLayer = fMCRec->fLayer; |
670 | 673 |
671 fSurfaceBase = nullptr; | 674 fSurfaceBase = nullptr; |
672 | 675 |
673 if (device) { | 676 if (device) { |
674 // The root device and the canvas should always have the same pixel geom etry | 677 // The root device and the canvas should always have the same pixel geom etry |
675 SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry( )); | 678 SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry( )); |
676 device->onAttachToCanvas(this); | 679 device->onAttachToCanvas(this); |
677 fMCRec->fLayer->fDevice = SkRef(device); | 680 fMCRec->fLayer->fDevice = SkRef(device); |
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1186 | 1189 |
1187 void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra tegy) { | 1190 void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra tegy) { |
1188 const SkRect* bounds = rec.fBounds; | 1191 const SkRect* bounds = rec.fBounds; |
1189 const SkPaint* paint = rec.fPaint; | 1192 const SkPaint* paint = rec.fPaint; |
1190 SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags; | 1193 SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags; |
1191 | 1194 |
1192 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG | 1195 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG |
1193 saveLayerFlags &= ~kDontClipToLayer_PrivateSaveLayerFlag; | 1196 saveLayerFlags &= ~kDontClipToLayer_PrivateSaveLayerFlag; |
1194 #endif | 1197 #endif |
1195 | 1198 |
1199 SkLazyPaint lazyP; | |
1200 SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL; | |
1201 SkMatrix stashedMatrix = fMCRec->fMatrix; | |
1202 #ifndef SK_SUPPORT_LEGACY_IMAGEFILTER_CTM | |
1203 SkMatrix remainder; | |
1204 SkSize scale; | |
1205 /* | |
1206 * ImageFilters (so far) do not correctly handle matrices (CTM) that contai n rotation/skew/etc. | |
1207 * but they do handle scaling. To accommodate this, we do the following: | |
1208 * | |
1209 * 1. Stash off the current CTM | |
1210 * 2. Decompose the CTM into SCALE and REMAINDER | |
1211 * 3. Wack the CTM to be just SCALE, and wrap the imagefilter with a Matrix ImageFilter that | |
1212 * contains the REMAINDER | |
1213 * 4. Proceed as usual, allowing the client to draw into the layer (now wit h a scale-only CTM) | |
1214 * 5. During restore, we process the MatrixImageFilter, which applies REMAI NDER to the output | |
1215 * of the original imagefilter, and draw that (via drawSprite) | |
1216 * 6. Unwack the CTM to its original state (i.e. stashedMatrix) | |
1217 * | |
1218 * Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer | |
1219 * a sprite operation) to avoid the extra buffer/overhead of MatrixImageFil ter. | |
1220 */ | |
1221 if (imageFilter && | |
1222 !stashedMatrix.isScaleTranslate() && | |
1223 stashedMatrix.decomposeScale(&scale, &remainder)) | |
1224 { | |
1225 // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix | |
1226 this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height( ))); | |
1227 SkPaint* p = lazyP.set(*paint); | |
1228 p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder, | |
1229 SkFilterQuality::kLow_ SkFilterQuality, | |
Stephen White
2016/04/20 18:39:34
Blink currently uses High quality in SkiaImageFilt
reed1
2016/04/20 19:42:50
My thinking was that since we decompose the scale,
Stephen White
2016/04/20 21:19:32
OK, let's give it a try.
| |
1230 sk_ref_sp(imageFilter) )); | |
1231 imageFilter = p->getImageFilter(); | |
1232 paint = p; | |
1233 } | |
1234 #endif | |
1235 | |
1196 // do this before we create the layer. We don't call the public save() since | 1236 // do this before we create the layer. We don't call the public save() since |
1197 // that would invoke a possibly overridden virtual | 1237 // that would invoke a possibly overridden virtual |
1198 this->internalSave(); | 1238 this->internalSave(); |
1199 | 1239 |
1200 fDeviceCMDirty = true; | 1240 fDeviceCMDirty = true; |
1201 | 1241 |
1202 SkIRect ir; | 1242 SkIRect ir; |
1203 if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, paint ? paint->getIma geFilter() : nullptr)) { | 1243 if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) { |
1204 return; | 1244 return; |
1205 } | 1245 } |
1206 | 1246 |
1207 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about | 1247 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about |
1208 // the clipRectBounds() call above? | 1248 // the clipRectBounds() call above? |
1209 if (kNoLayer_SaveLayerStrategy == strategy) { | 1249 if (kNoLayer_SaveLayerStrategy == strategy) { |
1210 return; | 1250 return; |
1211 } | 1251 } |
1212 | 1252 |
1213 bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag); | 1253 bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1249 forceSpriteOnRestore = true; | 1289 forceSpriteOnRestore = true; |
1250 } | 1290 } |
1251 device = newDev; | 1291 device = newDev; |
1252 } | 1292 } |
1253 device->setOrigin(ir.fLeft, ir.fTop); | 1293 device->setOrigin(ir.fLeft, ir.fTop); |
1254 | 1294 |
1255 if (rec.fBackdrop) { | 1295 if (rec.fBackdrop) { |
1256 draw_filter_into_device(fMCRec->fTopLayer->fDevice, rec.fBackdrop, devic e, fMCRec->fMatrix); | 1296 draw_filter_into_device(fMCRec->fTopLayer->fDevice, rec.fBackdrop, devic e, fMCRec->fMatrix); |
1257 } | 1297 } |
1258 | 1298 |
1259 DeviceCM* layer = | 1299 DeviceCM* layer = new DeviceCM(device, paint, this, fConservativeRasterClip, |
1260 new DeviceCM(device, paint, this, fConservativeRasterClip, forceSpri teOnRestore); | 1300 forceSpriteOnRestore, stashedMatrix); |
1261 device->unref(); | 1301 device->unref(); |
1262 | 1302 |
1263 layer->fNext = fMCRec->fTopLayer; | 1303 layer->fNext = fMCRec->fTopLayer; |
1264 fMCRec->fLayer = layer; | 1304 fMCRec->fLayer = layer; |
1265 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer | 1305 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer |
1266 } | 1306 } |
1267 | 1307 |
1268 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { | 1308 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { |
1269 if (0xFF == alpha) { | 1309 if (0xFF == alpha) { |
1270 return this->saveLayer(bounds, nullptr); | 1310 return this->saveLayer(bounds, nullptr); |
(...skipping 24 matching lines...) Expand all Loading... | |
1295 | 1335 |
1296 /* Time to draw the layer's offscreen. We can't call the public drawSprite, | 1336 /* 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 | 1337 since if we're being recorded, we don't want to record this (the |
1298 recorder will have already recorded the restore). | 1338 recorder will have already recorded the restore). |
1299 */ | 1339 */ |
1300 if (layer) { | 1340 if (layer) { |
1301 if (layer->fNext) { | 1341 if (layer->fNext) { |
1302 const SkIPoint& origin = layer->fDevice->getOrigin(); | 1342 const SkIPoint& origin = layer->fDevice->getOrigin(); |
1303 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), | 1343 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), |
1304 layer->fPaint, layer->fDeviceIsBitmapDevice ); | 1344 layer->fPaint, layer->fDeviceIsBitmapDevice ); |
1345 // restore what we smashed in internalSaveLayer | |
1346 fMCRec->fMatrix = layer->fStashedMatrix; | |
1305 // reset this, since internalDrawDevice will have set it to true | 1347 // reset this, since internalDrawDevice will have set it to true |
1306 fDeviceCMDirty = true; | 1348 fDeviceCMDirty = true; |
1307 delete layer; | 1349 delete layer; |
1308 } else { | 1350 } else { |
1309 // we're at the root | 1351 // we're at the root |
1310 SkASSERT(layer == (void*)fDeviceCMStorage); | 1352 SkASSERT(layer == (void*)fDeviceCMStorage); |
1311 layer->~DeviceCM(); | 1353 layer->~DeviceCM(); |
1354 // no need to update fMCRec, 'cause we're killing the canvas | |
1312 } | 1355 } |
1313 } | 1356 } |
1314 } | 1357 } |
1315 | 1358 |
1316 sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceP rops* props) { | 1359 sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceP rops* props) { |
1317 if (nullptr == props) { | 1360 if (nullptr == props) { |
1318 props = &fProps; | 1361 props = &fProps; |
1319 } | 1362 } |
1320 return this->onNewSurface(info, *props); | 1363 return this->onNewSurface(info, *props); |
1321 } | 1364 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1477 } | 1520 } |
1478 | 1521 |
1479 this->checkForDeferredSave(); | 1522 this->checkForDeferredSave(); |
1480 fDeviceCMDirty = true; | 1523 fDeviceCMDirty = true; |
1481 fCachedLocalClipBoundsDirty = true; | 1524 fCachedLocalClipBoundsDirty = true; |
1482 fMCRec->fMatrix.preConcat(matrix); | 1525 fMCRec->fMatrix.preConcat(matrix); |
1483 | 1526 |
1484 this->didConcat(matrix); | 1527 this->didConcat(matrix); |
1485 } | 1528 } |
1486 | 1529 |
1530 void SkCanvas::internalSetMatrix(const SkMatrix& matrix) { | |
1531 fDeviceCMDirty = true; | |
1532 fCachedLocalClipBoundsDirty = true; | |
1533 fMCRec->fMatrix = matrix; | |
1534 } | |
1535 | |
1487 void SkCanvas::setMatrix(const SkMatrix& matrix) { | 1536 void SkCanvas::setMatrix(const SkMatrix& matrix) { |
1488 this->checkForDeferredSave(); | 1537 this->checkForDeferredSave(); |
1489 fDeviceCMDirty = true; | 1538 this->internalSetMatrix(matrix); |
1490 fCachedLocalClipBoundsDirty = true; | |
1491 fMCRec->fMatrix = matrix; | |
1492 this->didSetMatrix(matrix); | 1539 this->didSetMatrix(matrix); |
1493 } | 1540 } |
1494 | 1541 |
1495 void SkCanvas::resetMatrix() { | 1542 void SkCanvas::resetMatrix() { |
1496 SkMatrix matrix; | 1543 this->setMatrix(SkMatrix::I()); |
1497 | |
1498 matrix.reset(); | |
1499 this->setMatrix(matrix); | |
1500 } | 1544 } |
1501 | 1545 |
1502 ////////////////////////////////////////////////////////////////////////////// | 1546 ////////////////////////////////////////////////////////////////////////////// |
1503 | 1547 |
1504 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { | 1548 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { |
1505 this->checkForDeferredSave(); | 1549 this->checkForDeferredSave(); |
1506 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; | 1550 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; |
1507 this->onClipRect(rect, op, edgeStyle); | 1551 this->onClipRect(rect, op, edgeStyle); |
1508 } | 1552 } |
1509 | 1553 |
(...skipping 1543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3053 | 3097 |
3054 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { | 3098 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { |
3055 fCanvas->restoreToCount(fSaveCount); | 3099 fCanvas->restoreToCount(fSaveCount); |
3056 } | 3100 } |
3057 | 3101 |
3058 #ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API | 3102 #ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API |
3059 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p rops) { | 3103 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p rops) { |
3060 return this->makeSurface(info, props).release(); | 3104 return this->makeSurface(info, props).release(); |
3061 } | 3105 } |
3062 #endif | 3106 #endif |
OLD | NEW |