Index: cc/output/render_surface_filters.cc |
diff --git a/cc/output/render_surface_filters.cc b/cc/output/render_surface_filters.cc |
index fa84e67f4d3913dd66ef067eb55d72e031c6cd20..7325f83abd304f95719f0262e39f8c55e10c6da3 100644 |
--- a/cc/output/render_surface_filters.cc |
+++ b/cc/output/render_surface_filters.cc |
@@ -11,9 +11,13 @@ |
#include "cc/output/filter_operations.h" |
#include "skia/ext/refptr.h" |
#include "third_party/skia/include/core/SkCanvas.h" |
+#include "third_party/skia/include/core/SkFlattenableBuffers.h" |
+#include "third_party/skia/include/core/SkImageFilter.h" |
#include "third_party/skia/include/effects/SkBlurImageFilter.h" |
+#include "third_party/skia/include/effects/SkColorFilterImageFilter.h" |
#include "third_party/skia/include/effects/SkColorMatrixFilter.h" |
#include "third_party/skia/include/effects/SkMagnifierImageFilter.h" |
+#include "third_party/skia/include/effects/SkTestImageFilters.h" |
ajuma
2013/07/31 18:40:37
This is for SkComposeImageFilter, used to connect
Stephen White
2013/07/31 19:18:51
Yes, I think it should be broken out into its own
ajuma
2013/09/09 17:35:36
Done.
|
#include "third_party/skia/include/gpu/SkGpuDevice.h" |
#include "third_party/skia/include/gpu/SkGrPixelRef.h" |
#include "ui/gfx/size_f.h" |
@@ -231,6 +235,15 @@ bool GetColorMatrix(const FilterOperation& op, SkScalar matrix[20]) { |
} |
} |
+skia::RefPtr<SkImageFilter> CreateMatrixImageFilter( |
+ const SkScalar matrix[20], |
+ skia::RefPtr<SkImageFilter> input) { |
+ skia::RefPtr<SkColorFilter> color_filter = |
+ skia::AdoptRef(new SkColorMatrixFilter(matrix)); |
+ return skia::AdoptRef( |
+ SkColorFilterImageFilter::Create(color_filter.get(), input.get())); |
+} |
+ |
class FilterBufferState { |
public: |
FilterBufferState(GrContext* gr_context, |
@@ -309,6 +322,71 @@ class FilterBufferState { |
skia::RefPtr<SkCanvas> canvas_; |
}; |
+class DropShadowImageFilter : public SkImageFilter { |
ajuma
2013/07/31 18:40:37
This is copied from Blink. SkiaImageFilterBuilder
ajuma
2013/09/09 17:35:36
This is no longer needed, since DropShadowImageFil
|
+ public: |
+ DropShadowImageFilter(SkScalar dx, |
+ SkScalar dy, |
+ SkScalar sigma, |
+ SkColor color, |
+ SkImageFilter* input) |
+ : SkImageFilter(input), |
+ dx_(dx), |
+ dy_(dy), |
+ sigma_(sigma), |
+ color_(color) { } |
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(DropShadowImageFilter) |
+ |
+ protected: |
+ explicit DropShadowImageFilter(SkFlattenableReadBuffer& buffer) |
+ : SkImageFilter(buffer) { |
+ dx_ = buffer.readScalar(); |
+ dy_ = buffer.readScalar(); |
+ sigma_ = buffer.readScalar(); |
+ color_ = buffer.readColor(); |
+ } |
+ |
+ virtual void flatten(SkFlattenableWriteBuffer& buffer) const OVERRIDE { |
+ buffer.writeScalar(dx_); |
+ buffer.writeScalar(dy_); |
+ buffer.writeScalar(sigma_); |
+ buffer.writeColor(color_); |
+ } |
+ |
+ virtual bool onFilterImage(Proxy* proxy, |
+ const SkBitmap& source, |
+ const SkMatrix& matrix, |
+ SkBitmap* result, |
+ SkIPoint* loc) OVERRIDE { |
+ SkBitmap src = source; |
+ if (getInput(0) && |
+ !getInput(0)->filterImage(proxy, source, matrix, &src, loc)) |
+ return false; |
+ |
+ skia::RefPtr<SkDevice> device = skia::AdoptRef( |
+ proxy->createDevice(src.width(), src.height())); |
+ SkCanvas canvas(device.get()); |
+ |
+ skia::RefPtr<SkImageFilter> blurFilter = skia::AdoptRef( |
+ new SkBlurImageFilter(sigma_, sigma_)); |
+ skia::RefPtr<SkColorFilter> colorFilter = skia::AdoptRef( |
+ SkColorFilter::CreateModeFilter(color_, SkXfermode::kSrcIn_Mode)); |
+ SkPaint paint; |
+ paint.setImageFilter(blurFilter.get()); |
+ paint.setColorFilter(colorFilter.get()); |
+ paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); |
+ canvas.saveLayer(0, &paint); |
Stephen White
2013/07/31 19:18:51
FYI, we can probably get rid of the saveLayer()/re
|
+ canvas.drawBitmap(src, dx_, dy_); |
ajuma
2013/07/31 18:40:37
The version of DropShadowImageFilter currently in
Stephen White
2013/07/31 19:18:51
Yeah, I think that was when we had TopDown texture
|
+ canvas.restore(); |
+ canvas.drawBitmap(src, 0, 0); |
+ *result = device.get()->accessBitmap(false); |
+ return true; |
+ } |
+ |
+ private: |
+ SkScalar dx_, dy_, sigma_; |
+ SkColor color_; |
+}; |
+ |
} // namespace |
FilterOperations RenderSurfaceFilters::Optimize( |
@@ -355,6 +433,9 @@ FilterOperations RenderSurfaceFilters::Optimize( |
case FilterOperation::ZOOM: |
new_list.Append(op); |
break; |
+ case FilterOperation::REFERENCE: |
+ // Not supported on this code path. |
+ NOTREACHED(); |
case FilterOperation::BRIGHTNESS: |
case FilterOperation::SATURATING_BRIGHTNESS: |
case FilterOperation::CONTRAST: |
@@ -442,6 +523,7 @@ SkBitmap RenderSurfaceFilters::Apply(const FilterOperations& filters, |
canvas->restore(); |
break; |
} |
+ case FilterOperation::REFERENCE: |
case FilterOperation::BRIGHTNESS: |
case FilterOperation::SATURATING_BRIGHTNESS: |
case FilterOperation::CONTRAST: |
@@ -459,4 +541,91 @@ SkBitmap RenderSurfaceFilters::Apply(const FilterOperations& filters, |
return state.Source(); |
} |
+skia::RefPtr<SkImageFilter> RenderSurfaceFilters::BuildImageFilter( |
+ const FilterOperations& filters) { |
+ skia::RefPtr<SkImageFilter> image_filter; |
+ SkScalar matrix[20]; |
+ for (size_t i = 0; i < filters.size(); ++i) { |
+ const FilterOperation& op = filters.at(i); |
+ switch (op.type()) { |
+ case FilterOperation::GRAYSCALE: |
+ GetGrayscaleMatrix(1 - op.amount(), matrix); |
+ image_filter = CreateMatrixImageFilter(matrix, image_filter); |
+ break; |
+ case FilterOperation::SEPIA: |
+ GetSepiaMatrix(1 - op.amount(), matrix); |
+ image_filter = CreateMatrixImageFilter(matrix, image_filter); |
+ break; |
+ case FilterOperation::SATURATE: |
+ GetSaturateMatrix(op.amount(), matrix); |
+ image_filter = CreateMatrixImageFilter(matrix, image_filter); |
+ break; |
+ case FilterOperation::HUE_ROTATE: |
+ GetHueRotateMatrix(op.amount(), matrix); |
+ image_filter = CreateMatrixImageFilter(matrix, image_filter); |
+ break; |
+ case FilterOperation::INVERT: |
+ GetInvertMatrix(op.amount(), matrix); |
+ image_filter = CreateMatrixImageFilter(matrix, image_filter); |
+ break; |
+ case FilterOperation::OPACITY: |
+ GetOpacityMatrix(op.amount(), matrix); |
+ image_filter = CreateMatrixImageFilter(matrix, image_filter); |
+ break; |
+ case FilterOperation::BRIGHTNESS: |
+ GetBrightnessMatrix(op.amount(), matrix); |
+ image_filter = CreateMatrixImageFilter(matrix, image_filter); |
+ break; |
+ case FilterOperation::CONTRAST: |
+ GetContrastMatrix(op.amount(), matrix); |
+ image_filter = CreateMatrixImageFilter(matrix, image_filter); |
+ break; |
+ case FilterOperation::BLUR: |
+ image_filter = skia::AdoptRef(new SkBlurImageFilter( |
+ op.amount(), op.amount(), image_filter.get())); |
+ break; |
+ case FilterOperation::DROP_SHADOW: |
+ image_filter = skia::AdoptRef(new DropShadowImageFilter( |
+ SkIntToScalar(op.drop_shadow_offset().x()), |
+ SkIntToScalar(op.drop_shadow_offset().y()), |
+ SkIntToScalar(op.amount()), |
+ op.drop_shadow_color(), |
+ image_filter.get())); |
+ break; |
+ case FilterOperation::COLOR_MATRIX: |
+ image_filter = CreateMatrixImageFilter(op.matrix(), image_filter); |
+ break; |
+ case FilterOperation::ZOOM: |
+ // TODO(ajuma): Add support for this. Note that zoom filter operations |
+ // are only used for background filters right now. |
ajuma
2013/07/31 18:40:37
Is this worth doing? That is, are there any plans
Stephen White
2013/07/31 19:18:51
Check with zork@ about this filter; I think it's o
ajuma
2013/09/09 17:35:36
I've added the code that was missing here for ZOOM
|
+ NOTREACHED(); |
+ case FilterOperation::SATURATING_BRIGHTNESS: |
+ GetSaturatingBrightnessMatrix(op.amount(), matrix); |
+ image_filter = CreateMatrixImageFilter(matrix, image_filter); |
+ break; |
+ case FilterOperation::REFERENCE: { |
+ skia::RefPtr<SkColorFilter> cf; |
+ |
+ { |
+ SkColorFilter* colorfilter_rawptr = NULL; |
+ op.image_filter()->asColorFilter(&colorfilter_rawptr); |
+ cf = skia::AdoptRef(colorfilter_rawptr); |
+ } |
+ |
+ if (cf && cf->asColorMatrix(matrix) && |
+ !op.image_filter()->getInput(0)) { |
+ image_filter = CreateMatrixImageFilter(matrix, image_filter); |
+ } else if (image_filter.get()) { |
+ image_filter = skia::AdoptRef(new SkComposeImageFilter( |
+ op.image_filter().get(), image_filter.get())); |
ajuma
2013/07/31 18:40:37
The plan is to use a no-op filter as the SourceGra
Stephen White
2013/07/31 19:18:51
That seems reasonable. I like the use of the SkCom
|
+ } else { |
+ image_filter = op.image_filter(); |
+ } |
+ break; |
+ } |
+ } |
+ } |
+ return image_filter; |
+} |
+ |
} // namespace cc |