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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 these are used (assuming we're not on a layer) we rebuild these cache | 106 these are used (assuming we're not on a layer) we rebuild these cache |
107 values: they reflect the top of the save stack, but translated and clipped | 107 values: they reflect the top of the save stack, but translated and clipped |
108 by the device's XY offset and bitmap-bounds. | 108 by the device's XY offset and bitmap-bounds. |
109 */ | 109 */ |
110 struct DeviceCM { | 110 struct DeviceCM { |
111 DeviceCM* fNext; | 111 DeviceCM* fNext; |
112 SkBaseDevice* fDevice; | 112 SkBaseDevice* fDevice; |
113 SkRasterClip fClip; | 113 SkRasterClip fClip; |
114 const SkMatrix* fMatrix; | 114 const SkMatrix* fMatrix; |
115 SkPaint* fPaint; // may be null (in the future) | 115 SkPaint* fPaint; // may be null (in the future) |
| 116 SkMatrix fStashedMatrix; |
| 117 SkMatrix fExtraMatrix; |
116 | 118 |
117 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, | 119 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, |
118 bool conservativeRasterClip) | 120 bool conservativeRasterClip, const SkMatrix& stashedMatrix, |
| 121 const SkMatrix& extraMatrix) |
119 : fNext(NULL) | 122 : fNext(NULL) |
120 , fClip(conservativeRasterClip) | 123 , fClip(conservativeRasterClip) |
| 124 , fStashedMatrix(stashedMatrix) |
| 125 , fExtraMatrix(extraMatrix) |
121 { | 126 { |
122 if (NULL != device) { | 127 if (NULL != device) { |
123 device->ref(); | 128 device->ref(); |
124 device->onAttachToCanvas(canvas); | 129 device->onAttachToCanvas(canvas); |
125 } | 130 } |
126 fDevice = device; | 131 fDevice = device; |
127 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; | 132 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; |
128 } | 133 } |
129 | 134 |
130 ~DeviceCM() { | 135 ~DeviceCM() { |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 fCachedLocalClipBoundsDirty = true; | 436 fCachedLocalClipBoundsDirty = true; |
432 fAllowSoftClip = true; | 437 fAllowSoftClip = true; |
433 fAllowSimplifyClip = false; | 438 fAllowSimplifyClip = false; |
434 fDeviceCMDirty = true; | 439 fDeviceCMDirty = true; |
435 fSaveCount = 1; | 440 fSaveCount = 1; |
436 fMetaData = NULL; | 441 fMetaData = NULL; |
437 | 442 |
438 fMCRec = (MCRec*)fMCStack.push_back(); | 443 fMCRec = (MCRec*)fMCStack.push_back(); |
439 new (fMCRec) MCRec(fConservativeRasterClip); | 444 new (fMCRec) MCRec(fConservativeRasterClip); |
440 | 445 |
441 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, NULL, NULL, fConservativeRaster
Clip)); | 446 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, NULL, NULL, fConservativeRaster
Clip, fMCRec->fMatrix, SkMatrix::I())); |
442 fMCRec->fTopLayer = fMCRec->fLayer; | 447 fMCRec->fTopLayer = fMCRec->fLayer; |
443 | 448 |
444 fSurfaceBase = NULL; | 449 fSurfaceBase = NULL; |
445 | 450 |
446 fClipStack.reset(SkNEW(SkClipStack)); | 451 fClipStack.reset(SkNEW(SkClipStack)); |
447 | 452 |
448 if (device) { | 453 if (device) { |
449 device->initForRootLayer(fProps.pixelGeometry()); | 454 device->initForRootLayer(fProps.pixelGeometry()); |
450 if (device->forceConservativeRasterClip()) { | 455 if (device->forceConservativeRasterClip()) { |
451 fConservativeRasterClip = true; | 456 fConservativeRasterClip = true; |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 | 829 |
825 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { | 830 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { |
826 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG | 831 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG |
827 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; | 832 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; |
828 #else | 833 #else |
829 return true; | 834 return true; |
830 #endif | 835 #endif |
831 } | 836 } |
832 | 837 |
833 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, | 838 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, |
834 SkIRect* intersection, const SkImageFilter* imageF
ilter) { | 839 SkIRect* intersection, const SkImageFilter* imageF
ilter, |
| 840 const SkMatrix* shearAndRotateMatrix) { |
835 SkIRect clipBounds; | 841 SkIRect clipBounds; |
836 if (!this->getClipDeviceBounds(&clipBounds)) { | 842 if (!this->getClipDeviceBounds(&clipBounds)) { |
837 return false; | 843 return false; |
838 } | 844 } |
839 | 845 |
840 const SkMatrix& ctm = fMCRec->fMatrix; // this->getTotalMatrix() | 846 const SkMatrix& ctm = fMCRec->fMatrix; // this->getTotalMatrix() |
841 | 847 |
842 if (imageFilter) { | 848 if (imageFilter) { |
| 849 if (shearAndRotateMatrix) { |
| 850 SkMatrix shearAndRotateInverse; |
| 851 if (!shearAndRotateMatrix->invert(&shearAndRotateInverse)) { |
| 852 return false; |
| 853 } |
| 854 SkMatrix matrix; |
| 855 if (!ctm.invert(&matrix)) { |
| 856 return false; |
| 857 } |
| 858 matrix.postConcat(shearAndRotateInverse); |
| 859 matrix.postConcat(ctm); |
| 860 SkRect floatBounds; |
| 861 matrix.mapRect(&floatBounds, SkRect::Make(clipBounds)); |
| 862 clipBounds = floatBounds.roundOut(); |
| 863 } |
843 imageFilter->filterBounds(clipBounds, ctm, &clipBounds); | 864 imageFilter->filterBounds(clipBounds, ctm, &clipBounds); |
844 } | 865 } |
| 866 |
845 SkIRect ir; | 867 SkIRect ir; |
846 if (bounds) { | 868 if (bounds) { |
847 SkRect r; | 869 SkRect r; |
848 | 870 |
849 ctm.mapRect(&r, *bounds); | 871 ctm.mapRect(&r, *bounds); |
850 r.roundOut(&ir); | 872 r.roundOut(&ir); |
851 // early exit if the layer's bounds are clipped out | 873 // early exit if the layer's bounds are clipped out |
852 if (!ir.intersect(clipBounds)) { | 874 if (!ir.intersect(clipBounds)) { |
853 if (bounds_affects_clip(flags)) { | 875 if (bounds_affects_clip(flags)) { |
854 fCachedLocalClipBoundsDirty = true; | 876 fCachedLocalClipBoundsDirty = true; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
892 fSaveCount += 1; | 914 fSaveCount += 1; |
893 this->internalSaveLayer(bounds, paint, flags, strategy); | 915 this->internalSaveLayer(bounds, paint, flags, strategy); |
894 return this->getSaveCount() - 1; | 916 return this->getSaveCount() - 1; |
895 } | 917 } |
896 | 918 |
897 void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
eFlags flags, | 919 void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav
eFlags flags, |
898 SaveLayerStrategy strategy) { | 920 SaveLayerStrategy strategy) { |
899 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG | 921 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG |
900 flags |= kClipToLayer_SaveFlag; | 922 flags |= kClipToLayer_SaveFlag; |
901 #endif | 923 #endif |
| 924 SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL; |
| 925 SkMatrix matrix = fMCRec->fMatrix; |
| 926 SkMatrix shearAndRotate = SkMatrix::I(); |
| 927 bool doShearAndRotate = false; |
| 928 if (imageFilter && !matrix.isScaleTranslate()) { |
| 929 doShearAndRotate = true; |
| 930 SkMatrix scaleAndTranslate; |
| 931 scaleAndTranslate.setTranslate(matrix.getTranslateX(), matrix.getTransla
teY()); |
| 932 SkScalar xScale = SkScalarSqrt(matrix[0] * matrix[0] + matrix[3] * matri
x[3]); |
| 933 SkScalar yScale = SkScalarSqrt(matrix[1] * matrix[1] + matrix[4] * matri
x[4]); |
| 934 scaleAndTranslate.postScale(xScale, yScale); |
| 935 if (!scaleAndTranslate.invert(&shearAndRotate)) { |
| 936 SkASSERT(false); |
| 937 } |
| 938 shearAndRotate.preConcat(matrix); |
| 939 fMCRec->fMatrix = scaleAndTranslate; |
| 940 } |
902 | 941 |
903 // do this before we create the layer. We don't call the public save() since | 942 // do this before we create the layer. We don't call the public save() since |
904 // that would invoke a possibly overridden virtual | 943 // that would invoke a possibly overridden virtual |
905 this->internalSave(); | 944 this->internalSave(); |
906 | 945 |
907 fDeviceCMDirty = true; | 946 fDeviceCMDirty = true; |
908 | 947 |
909 SkIRect ir; | 948 SkIRect ir; |
910 if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter(
) : NULL)) { | 949 if (!this->clipRectBounds(bounds, flags, &ir, imageFilter, doShearAndRotate
? &shearAndRotate : NULL)) { |
911 return; | 950 return; |
912 } | 951 } |
913 | 952 |
914 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy
really care about | 953 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy
really care about |
915 // the clipRectBounds() call above? | 954 // the clipRectBounds() call above? |
916 if (kNoLayer_SaveLayerStrategy == strategy) { | 955 if (kNoLayer_SaveLayerStrategy == strategy) { |
917 return; | 956 return; |
918 } | 957 } |
919 | 958 |
920 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); | 959 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); |
(...skipping 23 matching lines...) Expand all Loading... |
944 #endif | 983 #endif |
945 device = device->onCreateDevice(SkBaseDevice::CreateInfo(info, usage, fProps
.pixelGeometry()), | 984 device = device->onCreateDevice(SkBaseDevice::CreateInfo(info, usage, fProps
.pixelGeometry()), |
946 paint); | 985 paint); |
947 if (NULL == device) { | 986 if (NULL == device) { |
948 SkErrorInternals::SetError( kInternalError_SkError, | 987 SkErrorInternals::SetError( kInternalError_SkError, |
949 "Unable to create device for layer."); | 988 "Unable to create device for layer."); |
950 return; | 989 return; |
951 } | 990 } |
952 | 991 |
953 device->setOrigin(ir.fLeft, ir.fTop); | 992 device->setOrigin(ir.fLeft, ir.fTop); |
954 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRa
sterClip)); | 993 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRa
sterClip, matrix, shearAndRotate)); |
955 device->unref(); | 994 device->unref(); |
956 | 995 |
957 layer->fNext = fMCRec->fTopLayer; | 996 layer->fNext = fMCRec->fTopLayer; |
958 fMCRec->fLayer = layer; | 997 fMCRec->fLayer = layer; |
959 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer | 998 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer |
960 } | 999 } |
961 | 1000 |
962 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { | 1001 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { |
963 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag); | 1002 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag); |
964 } | 1003 } |
(...skipping 28 matching lines...) Expand all Loading... |
993 fMCRec = (MCRec*)fMCStack.back(); | 1032 fMCRec = (MCRec*)fMCStack.back(); |
994 | 1033 |
995 /* Time to draw the layer's offscreen. We can't call the public drawSprite, | 1034 /* Time to draw the layer's offscreen. We can't call the public drawSprite, |
996 since if we're being recorded, we don't want to record this (the | 1035 since if we're being recorded, we don't want to record this (the |
997 recorder will have already recorded the restore). | 1036 recorder will have already recorded the restore). |
998 */ | 1037 */ |
999 if (layer) { | 1038 if (layer) { |
1000 if (layer->fNext) { | 1039 if (layer->fNext) { |
1001 const SkIPoint& origin = layer->fDevice->getOrigin(); | 1040 const SkIPoint& origin = layer->fDevice->getOrigin(); |
1002 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), | 1041 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), |
1003 layer->fPaint); | 1042 layer->fPaint, layer->fExtraMatrix); |
1004 // reset this, since internalDrawDevice will have set it to true | 1043 // reset this, since internalDrawDevice will have set it to true |
1005 fDeviceCMDirty = true; | 1044 fDeviceCMDirty = true; |
1006 } | 1045 } |
| 1046 if (layer->fPaint && layer->fPaint->fImageFilter) { |
| 1047 fMCRec->fMatrix = layer->fStashedMatrix; |
| 1048 } |
1007 SkDELETE(layer); | 1049 SkDELETE(layer); |
1008 } | 1050 } |
1009 } | 1051 } |
1010 | 1052 |
1011 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p
rops) { | 1053 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p
rops) { |
1012 if (NULL == props) { | 1054 if (NULL == props) { |
1013 props = &fProps; | 1055 props = &fProps; |
1014 } | 1056 } |
1015 return this->onNewSurface(info, *props); | 1057 return this->onNewSurface(info, *props); |
1016 } | 1058 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) | 1143 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) |
1102 | 1144 |
1103 while (iter.next()) { | 1145 while (iter.next()) { |
1104 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); | 1146 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); |
1105 } | 1147 } |
1106 | 1148 |
1107 LOOPER_END | 1149 LOOPER_END |
1108 } | 1150 } |
1109 | 1151 |
1110 void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, | 1152 void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, |
1111 const SkPaint* paint) { | 1153 const SkPaint* paint, const SkMatrix& extraMat
rix) { |
1112 SkPaint tmp; | 1154 SkPaint tmp; |
1113 if (NULL == paint) { | 1155 if (NULL == paint) { |
1114 paint = &tmp; | 1156 paint = &tmp; |
1115 } | 1157 } |
1116 | 1158 |
1117 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) | 1159 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) |
1118 while (iter.next()) { | 1160 while (iter.next()) { |
1119 SkBaseDevice* dstDev = iter.fDevice; | 1161 SkBaseDevice* dstDev = iter.fDevice; |
1120 paint = &looper.paint(); | 1162 paint = &looper.paint(); |
1121 SkImageFilter* filter = paint->getImageFilter(); | 1163 SkImageFilter* filter = paint->getImageFilter(); |
1122 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; | 1164 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; |
1123 if (filter && !dstDev->canHandleImageFilter(filter)) { | 1165 if (filter && !dstDev->canHandleImageFilter(filter)) { |
1124 SkDeviceImageFilterProxy proxy(dstDev, fProps); | 1166 SkDeviceImageFilterProxy proxy(dstDev, fProps); |
1125 SkBitmap dst; | 1167 SkBitmap dst; |
1126 SkIPoint offset = SkIPoint::Make(0, 0); | 1168 SkIPoint offset = SkIPoint::Make(0, 0); |
1127 const SkBitmap& src = srcDev->accessBitmap(false); | 1169 const SkBitmap& src = srcDev->accessBitmap(false); |
1128 SkMatrix matrix = *iter.fMatrix; | 1170 SkMatrix matrix = *iter.fMatrix; |
1129 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()
)); | 1171 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()
)); |
1130 SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height
()); | 1172 SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height
()); |
1131 SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache
()); | 1173 SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache
()); |
1132 SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); | 1174 SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); |
1133 if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) { | 1175 if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) { |
1134 SkPaint tmpUnfiltered(*paint); | 1176 SkPaint tmpUnfiltered(*paint); |
1135 tmpUnfiltered.setImageFilter(NULL); | 1177 tmpUnfiltered.setImageFilter(NULL); |
1136 dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + of
fset.y(), | 1178 if (extraMatrix.isIdentity()) { |
1137 tmpUnfiltered); | 1179 offset += pos; |
| 1180 dstDev->drawSprite(iter, dst, offset.x(), offset.y(), |
| 1181 tmpUnfiltered); |
| 1182 } else { |
| 1183 SkMatrix matrix = extraMatrix; |
| 1184 matrix.preTranslate(offset.x(), offset.y()); |
| 1185 dstDev->drawBitmap(iter, dst, matrix, |
| 1186 tmpUnfiltered); |
| 1187 } |
1138 } | 1188 } |
1139 } else { | 1189 } else { |
1140 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); | 1190 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); |
1141 } | 1191 } |
1142 } | 1192 } |
1143 LOOPER_END | 1193 LOOPER_END |
1144 } | 1194 } |
1145 | 1195 |
1146 void SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint*
paint) { | 1196 void SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint*
paint) { |
1147 if (gTreatSpriteAsBitmap) { | 1197 if (gTreatSpriteAsBitmap) { |
(...skipping 1371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2519 } | 2569 } |
2520 | 2570 |
2521 if (matrix) { | 2571 if (matrix) { |
2522 canvas->concat(*matrix); | 2572 canvas->concat(*matrix); |
2523 } | 2573 } |
2524 } | 2574 } |
2525 | 2575 |
2526 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { | 2576 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { |
2527 fCanvas->restoreToCount(fSaveCount); | 2577 fCanvas->restoreToCount(fSaveCount); |
2528 } | 2578 } |
OLD | NEW |