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 "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 Loading... |
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 | |
119 const bool fDeviceIsBitmapDevice; | 118 const bool fDeviceIsBitmapDevice; |
120 | 119 |
121 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, | 120 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, |
122 bool conservativeRasterClip, bool deviceIsBitmapDevice, const SkMat
rix& stashed) | 121 bool conservativeRasterClip, bool deviceIsBitmapDevice) |
123 : fNext(NULL) | 122 : fNext(NULL) |
124 , fClip(conservativeRasterClip) | 123 , fClip(conservativeRasterClip) |
125 , fStashedMatrix(stashed) | |
126 , fDeviceIsBitmapDevice(deviceIsBitmapDevice) | 124 , fDeviceIsBitmapDevice(deviceIsBitmapDevice) |
127 { | 125 { |
128 if (NULL != device) { | 126 if (NULL != device) { |
129 device->ref(); | 127 device->ref(); |
130 device->onAttachToCanvas(canvas); | 128 device->onAttachToCanvas(canvas); |
131 } | 129 } |
132 fDevice = device; | 130 fDevice = device; |
133 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; | 131 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; |
134 } | 132 } |
135 | 133 |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 fSaveCount = 1; | 521 fSaveCount = 1; |
524 fMetaData = NULL; | 522 fMetaData = NULL; |
525 | 523 |
526 fClipStack.reset(SkNEW(SkClipStack)); | 524 fClipStack.reset(SkNEW(SkClipStack)); |
527 | 525 |
528 fMCRec = (MCRec*)fMCStack.push_back(); | 526 fMCRec = (MCRec*)fMCStack.push_back(); |
529 new (fMCRec) MCRec(fConservativeRasterClip); | 527 new (fMCRec) MCRec(fConservativeRasterClip); |
530 | 528 |
531 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); | 529 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); |
532 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage; | 530 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage; |
533 new (fDeviceCMStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, f
alse, | 531 new (fDeviceCMStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, f
alse); |
534 fMCRec->fMatrix); | |
535 | 532 |
536 fMCRec->fTopLayer = fMCRec->fLayer; | 533 fMCRec->fTopLayer = fMCRec->fLayer; |
537 | 534 |
538 fSurfaceBase = NULL; | 535 fSurfaceBase = NULL; |
539 | 536 |
540 if (device) { | 537 if (device) { |
541 device->initForRootLayer(fProps.pixelGeometry()); | 538 device->initForRootLayer(fProps.pixelGeometry()); |
542 if (device->forceConservativeRasterClip()) { | 539 if (device->forceConservativeRasterClip()) { |
543 fConservativeRasterClip = true; | 540 fConservativeRasterClip = true; |
544 } | 541 } |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 fSaveCount += 1; | 984 fSaveCount += 1; |
988 this->internalSaveLayer(bounds, paint, flags, strategy); | 985 this->internalSaveLayer(bounds, paint, flags, strategy); |
989 return this->getSaveCount() - 1; | 986 return this->getSaveCount() - 1; |
990 } | 987 } |
991 | 988 |
992 void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
eFlags flags, | 989 void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
eFlags flags, |
993 SaveLayerStrategy strategy) { | 990 SaveLayerStrategy strategy) { |
994 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG | 991 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG |
995 flags |= kClipToLayer_SaveFlag; | 992 flags |= kClipToLayer_SaveFlag; |
996 #endif | 993 #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 | |
1031 | 994 |
1032 // do this before we create the layer. We don't call the public save() since | 995 // do this before we create the layer. We don't call the public save() since |
1033 // that would invoke a possibly overridden virtual | 996 // that would invoke a possibly overridden virtual |
1034 this->internalSave(); | 997 this->internalSave(); |
1035 | 998 |
1036 fDeviceCMDirty = true; | 999 fDeviceCMDirty = true; |
1037 | 1000 |
1038 SkIRect ir; | 1001 SkIRect ir; |
1039 if (!this->clipRectBounds(bounds, flags, &ir, imageFilter)) { | 1002 if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter(
) : NULL)) { |
1040 return; | 1003 return; |
1041 } | 1004 } |
1042 | 1005 |
1043 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy
really care about | 1006 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy
really care about |
1044 // the clipRectBounds() call above? | 1007 // the clipRectBounds() call above? |
1045 if (kNoLayer_SaveLayerStrategy == strategy) { | 1008 if (kNoLayer_SaveLayerStrategy == strategy) { |
1046 return; | 1009 return; |
1047 } | 1010 } |
1048 | 1011 |
1049 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); | 1012 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); |
(...skipping 27 matching lines...) Expand all Loading... |
1077 "Unable to create device for layer.")
; | 1040 "Unable to create device for layer.")
; |
1078 return; | 1041 return; |
1079 } | 1042 } |
1080 forceSpriteOnRestore = true; | 1043 forceSpriteOnRestore = true; |
1081 } | 1044 } |
1082 device = newDev; | 1045 device = newDev; |
1083 } | 1046 } |
1084 | 1047 |
1085 device->setOrigin(ir.fLeft, ir.fTop); | 1048 device->setOrigin(ir.fLeft, ir.fTop); |
1086 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRa
sterClip, | 1049 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRa
sterClip, |
1087 forceSpriteOnRestore, stashedMatrix)
); | 1050 forceSpriteOnRestore)); |
1088 device->unref(); | 1051 device->unref(); |
1089 | 1052 |
1090 layer->fNext = fMCRec->fTopLayer; | 1053 layer->fNext = fMCRec->fTopLayer; |
1091 fMCRec->fLayer = layer; | 1054 fMCRec->fLayer = layer; |
1092 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer | 1055 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer |
1093 } | 1056 } |
1094 | 1057 |
1095 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { | 1058 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { |
1096 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag); | 1059 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag); |
1097 } | 1060 } |
(...skipping 29 matching lines...) Expand all Loading... |
1127 | 1090 |
1128 /* Time to draw the layer's offscreen. We can't call the public drawSprite, | 1091 /* Time to draw the layer's offscreen. We can't call the public drawSprite, |
1129 since if we're being recorded, we don't want to record this (the | 1092 since if we're being recorded, we don't want to record this (the |
1130 recorder will have already recorded the restore). | 1093 recorder will have already recorded the restore). |
1131 */ | 1094 */ |
1132 if (layer) { | 1095 if (layer) { |
1133 if (layer->fNext) { | 1096 if (layer->fNext) { |
1134 const SkIPoint& origin = layer->fDevice->getOrigin(); | 1097 const SkIPoint& origin = layer->fDevice->getOrigin(); |
1135 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), | 1098 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), |
1136 layer->fPaint, layer->fDeviceIsBitmapDevice
); | 1099 layer->fPaint, layer->fDeviceIsBitmapDevice
); |
1137 // restore what we smashed in internalSaveLayer | |
1138 fMCRec->fMatrix = layer->fStashedMatrix; | |
1139 // reset this, since internalDrawDevice will have set it to true | 1100 // reset this, since internalDrawDevice will have set it to true |
1140 fDeviceCMDirty = true; | 1101 fDeviceCMDirty = true; |
1141 SkDELETE(layer); | 1102 SkDELETE(layer); |
1142 } else { | 1103 } else { |
1143 // we're at the root | 1104 // we're at the root |
1144 SkASSERT(layer == (void*)fDeviceCMStorage); | 1105 SkASSERT(layer == (void*)fDeviceCMStorage); |
1145 layer->~DeviceCM(); | 1106 layer->~DeviceCM(); |
1146 // no need to update fMCRec, 'cause we're killing the canvas | |
1147 } | 1107 } |
1148 } | 1108 } |
1149 } | 1109 } |
1150 | 1110 |
1151 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p
rops) { | 1111 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p
rops) { |
1152 if (NULL == props) { | 1112 if (NULL == props) { |
1153 props = &fProps; | 1113 props = &fProps; |
1154 } | 1114 } |
1155 return this->onNewSurface(info, *props); | 1115 return this->onNewSurface(info, *props); |
1156 } | 1116 } |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 } | 1325 } |
1366 | 1326 |
1367 this->checkForDeferredSave(); | 1327 this->checkForDeferredSave(); |
1368 fDeviceCMDirty = true; | 1328 fDeviceCMDirty = true; |
1369 fCachedLocalClipBoundsDirty = true; | 1329 fCachedLocalClipBoundsDirty = true; |
1370 fMCRec->fMatrix.preConcat(matrix); | 1330 fMCRec->fMatrix.preConcat(matrix); |
1371 | 1331 |
1372 this->didConcat(matrix); | 1332 this->didConcat(matrix); |
1373 } | 1333 } |
1374 | 1334 |
1375 void SkCanvas::internalSetMatrix(const SkMatrix& matrix) { | |
1376 fDeviceCMDirty = true; | |
1377 fCachedLocalClipBoundsDirty = true; | |
1378 fMCRec->fMatrix = matrix; | |
1379 } | |
1380 | |
1381 void SkCanvas::setMatrix(const SkMatrix& matrix) { | 1335 void SkCanvas::setMatrix(const SkMatrix& matrix) { |
1382 this->checkForDeferredSave(); | 1336 this->checkForDeferredSave(); |
1383 this->internalSetMatrix(matrix); | 1337 fDeviceCMDirty = true; |
| 1338 fCachedLocalClipBoundsDirty = true; |
| 1339 fMCRec->fMatrix = matrix; |
1384 this->didSetMatrix(matrix); | 1340 this->didSetMatrix(matrix); |
1385 } | 1341 } |
1386 | 1342 |
1387 void SkCanvas::resetMatrix() { | 1343 void SkCanvas::resetMatrix() { |
1388 SkMatrix matrix; | 1344 SkMatrix matrix; |
1389 | 1345 |
1390 matrix.reset(); | 1346 matrix.reset(); |
1391 this->setMatrix(matrix); | 1347 this->setMatrix(matrix); |
1392 } | 1348 } |
1393 | 1349 |
(...skipping 1337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2731 } | 2687 } |
2732 | 2688 |
2733 if (matrix) { | 2689 if (matrix) { |
2734 canvas->concat(*matrix); | 2690 canvas->concat(*matrix); |
2735 } | 2691 } |
2736 } | 2692 } |
2737 | 2693 |
2738 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { | 2694 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { |
2739 fCanvas->restoreToCount(fSaveCount); | 2695 fCanvas->restoreToCount(fSaveCount); |
2740 } | 2696 } |
OLD | NEW |