Chromium Code Reviews| Index: Source/core/platform/graphics/DrawLooper.cpp |
| diff --git a/Source/core/platform/graphics/DrawLooper.cpp b/Source/core/platform/graphics/DrawLooper.cpp |
| index 609878b0581bb183c0b7767780153ca99d316e76..b8de8c7f3ba4f1cd180ae0c918f8fd2591648779 100644 |
| --- a/Source/core/platform/graphics/DrawLooper.cpp |
| +++ b/Source/core/platform/graphics/DrawLooper.cpp |
| @@ -33,72 +33,169 @@ |
| #include "core/platform/graphics/Color.h" |
| #include "core/platform/graphics/FloatSize.h" |
| +#include "third_party/skia/include/core/SkBitmap.h" |
| #include "third_party/skia/include/core/SkColor.h" |
| #include "third_party/skia/include/core/SkColorFilter.h" |
| #include "third_party/skia/include/core/SkDrawLooper.h" |
| #include "third_party/skia/include/core/SkPaint.h" |
| #include "third_party/skia/include/core/SkXfermode.h" |
| #include "third_party/skia/include/effects/SkBlurMaskFilter.h" |
| +#include "third_party/skia/include/effects/SkDropShadowImageFilter.h" |
| #include "third_party/skia/include/effects/SkLayerDrawLooper.h" |
| namespace WebCore { |
| -DrawLooper::DrawLooper() : m_skDrawLooper(adoptRef(new SkLayerDrawLooper)) { } |
| +DrawLooper::DrawLooper() |
| +{ |
| + m_cachedDrawLooper.reset(0); |
| +} |
| DrawLooper::~DrawLooper() { } |
| -SkDrawLooper* DrawLooper::skDrawLooper() const |
| +SkDrawLooper* DrawLooper::skDrawLooper() |
| +{ |
| + if (!m_cachedDrawLooper.get()) |
| + buildCachedDrawLooper(); |
| + return m_cachedDrawLooper.get(); |
| +} |
| + |
| +SkImageFilter* DrawLooper::imageFilter() |
| { |
| - return m_skDrawLooper.get(); |
| + if (!m_cachedImageFilter.get()) |
| + buildCachedImageFilter(); |
| + return m_cachedImageFilter.get(); |
| +} |
| + |
| +void DrawLooper::clearCached() |
| +{ |
| + m_cachedDrawLooper.reset(0); |
| + m_cachedImageFilter.reset(0); |
| } |
| void DrawLooper::addUnmodifiedContent() |
| { |
| - SkLayerDrawLooper::LayerInfo info; |
| - m_skDrawLooper->addLayerOnTop(info); |
| + DrawLooperLayerInfo info; |
| + info.m_layerType = UnmodifiedLayer; |
| + m_layerInfo.append(info); |
| + clearCached(); |
| } |
| + |
|
jbroman
2013/08/23 19:59:38
Extra newline?
|
| void DrawLooper::addShadow(const FloatSize& offset, float blur, const Color& color, |
| ShadowTransformMode shadowTransformMode, ShadowAlphaMode shadowAlphaMode) |
| { |
| // Detect when there's no effective shadow. |
| if (!color.alpha()) |
| return; |
| + DrawLooperLayerInfo info; |
| + info.m_layerType = ShadowLayer; |
| + info.m_blur = blur; |
| + info.m_color = color; |
| + info.m_offset = offset; |
| + info.m_shadowAlphaMode = shadowAlphaMode; |
| + info.m_shadowTransformMode = shadowTransformMode; |
| + m_layerInfo.append(info); |
| + clearCached(); |
| +}; |
| + |
| +void DrawLooper::buildCachedDrawLooper() |
| +{ |
| + m_cachedDrawLooper.reset(new SkLayerDrawLooper); |
| + LayerVector::const_iterator info; |
| + for (info = m_layerInfo.begin(); info < m_layerInfo.end(); ++info) { |
| + if (info->m_layerType == ShadowLayer) { |
| + SkColor skColor = info->m_color.rgb(); |
| + |
| + SkLayerDrawLooper::LayerInfo skInfo; |
| + |
| + switch (info->m_shadowAlphaMode) { |
| + case ShadowRespectsAlpha: |
| + skInfo.fColorMode = SkXfermode::kDst_Mode; |
| + break; |
| + case ShadowIgnoresAlpha: |
| + skInfo.fColorMode = SkXfermode::kSrc_Mode; |
| + break; |
| + default: |
| + ASSERT_NOT_REACHED(); |
| + } |
| + |
| + if (info->m_blur) |
| + skInfo.fPaintBits |= SkLayerDrawLooper::kMaskFilter_Bit; // our blur |
| + skInfo.fPaintBits |= SkLayerDrawLooper::kColorFilter_Bit; |
| + skInfo.fOffset.set(info->m_offset.width(), info->m_offset.height()); |
| + skInfo.fPostTranslate = (info->m_shadowTransformMode == ShadowIgnoresTransforms); |
| + |
| + SkPaint* paint = m_cachedDrawLooper->addLayerOnTop(skInfo); |
| + |
| + if (info->m_blur) { |
| + uint32_t mfFlags = SkBlurMaskFilter::kHighQuality_BlurFlag; |
| + if (info->m_shadowTransformMode == ShadowIgnoresTransforms) |
| + mfFlags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag; |
| + RefPtr<SkMaskFilter> mf = adoptRef(SkBlurMaskFilter::Create( |
| + (double)info->m_blur / 2.0, SkBlurMaskFilter::kNormal_BlurStyle, mfFlags)); |
| + paint->setMaskFilter(mf.get()); |
| + } |
| + |
| + RefPtr<SkColorFilter> cf = adoptRef(SkColorFilter::CreateModeFilter(skColor, SkXfermode::kSrcIn_Mode)); |
| + paint->setColorFilter(cf.get()); |
| + } else { |
| + // Unmodified layer |
| + SkLayerDrawLooper::LayerInfo skInfo; |
| + m_cachedDrawLooper->addLayerOnTop(skInfo); |
| + } |
| + } |
| +} |
| - SkColor skColor = color.rgb(); |
| +void DrawLooper::buildCachedImageFilter() |
| +{ |
| + ASSERT(m_layerInfo.size() == 2); |
| + ASSERT(m_layerInfo[0].m_layerType == ShadowLayer); |
| + ASSERT(m_layerInfo[1].m_layerType == UnmodifiedLayer); |
| + ASSERT(m_layerInfo[0].m_shadowAlphaMode == ShadowRespectsAlpha); |
| + ASSERT(m_layerInfo[0].m_shadowTransformMode == ShadowIgnoresTransforms); |
| + const float blurToSigmaFactor = 0.25; |
| + SkColor skColor = m_layerInfo[0].m_color.rgb(); |
| + m_cachedImageFilter.reset(new SkDropShadowImageFilter(m_layerInfo[0].m_offset.width(), m_layerInfo[0].m_offset.height(), m_layerInfo[0].m_blur * blurToSigmaFactor, skColor)); |
| +} |
| - SkLayerDrawLooper::LayerInfo info; |
| +bool DrawLooper::shouldUseImageFilterToDrawBitmap(const SkBitmap& bitmap) |
| +{ |
| + if (bitmap.isOpaque() || !m_layerInfo.size()) |
| + return false; |
| + |
| +#if !ASSERT_DISABLED |
| + // Verify that cases that require a mask filter to render correctly are of |
| + // a form that can be handled by DropShadowImageFilter. |
| + LayerVector::const_iterator info; |
| + int unmodifiedCount = 0; |
| + int shadowCount = 0; |
| + bool needsFilter = false; |
| + for (info = m_layerInfo.begin(); info < m_layerInfo.end(); ++info) { |
| + if (info->m_layerType == ShadowLayer) { |
| + needsFilter = needsFilter || (info->m_blur && info->m_shadowAlphaMode == ShadowRespectsAlpha); |
| + shadowCount++; |
| + } else { |
| + unmodifiedCount++; |
| + } |
| - switch (shadowAlphaMode) { |
| - case ShadowRespectsAlpha: |
| - info.fColorMode = SkXfermode::kDst_Mode; |
| - break; |
| - case ShadowIgnoresAlpha: |
| - info.fColorMode = SkXfermode::kSrc_Mode; |
| - break; |
| - default: |
| - ASSERT_NOT_REACHED(); |
| } |
| - |
| - if (blur) |
| - info.fPaintBits |= SkLayerDrawLooper::kMaskFilter_Bit; // our blur |
| - info.fPaintBits |= SkLayerDrawLooper::kColorFilter_Bit; |
| - info.fOffset.set(offset.width(), offset.height()); |
| - info.fPostTranslate = (shadowTransformMode == ShadowIgnoresTransforms); |
| - |
| - SkPaint* paint = m_skDrawLooper->addLayerOnTop(info); |
| - |
| - if (blur) { |
| - uint32_t mfFlags = SkBlurMaskFilter::kHighQuality_BlurFlag; |
| - if (shadowTransformMode == ShadowIgnoresTransforms) |
| - mfFlags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag; |
| - RefPtr<SkMaskFilter> mf = adoptRef(SkBlurMaskFilter::Create( |
| - (double)blur / 2.0, SkBlurMaskFilter::kNormal_BlurStyle, mfFlags)); |
| - paint->setMaskFilter(mf.get()); |
| + if (needsFilter) { |
| + // If any of the following assertions ever fire, it means that we are hitting |
| + // case that may not be rendered correclty by the DrawLooper and cannot be |
| + // handled by DropShadowImageFilter. |
| + ASSERT(shadowCount == 1); |
| + ASSERT(unmodifiedCount == 1); |
| + ASSERT(m_layerInfo[0].m_layerType == ShadowLayer); |
| + ASSERT(m_layerInfo[0].m_shadowTransformMode == ShadowIgnoresTransforms); |
| } |
| - |
| - RefPtr<SkColorFilter> cf = adoptRef(SkColorFilter::CreateModeFilter(skColor, SkXfermode::kSrcIn_Mode)); |
| - paint->setColorFilter(cf.get()); |
| +#endif |
| + |
| + return m_layerInfo.size() == 2 |
| + && m_layerInfo[0].m_layerType == ShadowLayer |
| + && m_layerInfo[0].m_shadowAlphaMode == ShadowRespectsAlpha |
| + && m_layerInfo[0].m_shadowTransformMode == ShadowIgnoresTransforms |
| + && m_layerInfo[0].m_blur |
| + && m_layerInfo[1].m_layerType == UnmodifiedLayer; |
| } |
| } // namespace WebCore |