| 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 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |