Modified: trunk/Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp (208572 => 208573)
--- trunk/Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp 2016-11-11 00:49:06 UTC (rev 208572)
+++ trunk/Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp 2016-11-11 00:59:53 UTC (rev 208573)
@@ -151,10 +151,31 @@
ID2D1RenderTarget* GraphicsContext::platformContext() const
{
ASSERT(!paintingDisabled());
- ASSERT(m_data->renderTarget());
return m_data->renderTarget();
}
+ID2D1RenderTarget* GraphicsContextPlatformPrivate::renderTarget()
+{
+ if (!m_transparencyLayerStack.isEmpty())
+ return m_transparencyLayerStack.last().renderTarget.get();
+
+ return m_renderTarget.get();
+}
+
+void GraphicsContextPlatformPrivate::setAlpha(float alpha)
+{
+ ASSERT(m_transparencyLayerStack.isEmpty());
+ m_alpha = alpha;
+}
+
+float GraphicsContextPlatformPrivate::currentGlobalAlpha() const
+{
+ if (!m_transparencyLayerStack.isEmpty())
+ return m_transparencyLayerStack.last().opacity;
+
+ return m_alpha;
+}
+
void GraphicsContext::savePlatformState()
{
ASSERT(!paintingDisabled());
@@ -489,8 +510,8 @@
D2D1_COLOR_F GraphicsContext::colorWithGlobalAlpha(const Color& color) const
{
- float colorAlpha = color.alpha() / 255.0f;
- float globalAlpha = m_state.alpha;
+ float colorAlpha = color.alphaAsFloat();
+ float globalAlpha = m_data->currentGlobalAlpha();
return D2D1::ColorF(color.rgb(), globalAlpha * colorAlpha);
}
@@ -919,26 +940,10 @@
drawCommands(platformContext());
}
-void GraphicsContext::drawWithShadow(const FloatRect& boundingRect, const std::function<void(ID2D1RenderTarget*)>& drawCommands)
+static void drawWithShadowHelper(ID2D1RenderTarget* context, ID2D1Bitmap* bitmap, const Color& shadowColor, const FloatSize& shadowOffset, float shadowBlur)
{
- auto context = platformContext();
-
- // Render the current geometry to a bitmap context
- COMPtr<ID2D1BitmapRenderTarget> bitmapTarget;
- HRESULT hr = context->CreateCompatibleRenderTarget(&bitmapTarget);
- RELEASE_ASSERT(SUCCEEDED(hr));
-
- bitmapTarget->BeginDraw();
- drawCommands(bitmapTarget.get());
- hr = bitmapTarget->EndDraw();
- RELEASE_ASSERT(SUCCEEDED(hr));
-
- COMPtr<ID2D1Bitmap> bitmap;
- hr = bitmapTarget->GetBitmap(&bitmap);
- RELEASE_ASSERT(SUCCEEDED(hr));
-
COMPtr<ID2D1DeviceContext> deviceContext;
- hr = context->QueryInterface(&deviceContext);
+ HRESULT hr = context->QueryInterface(&deviceContext);
RELEASE_ASSERT(SUCCEEDED(hr));
// Create the shadow effect
@@ -946,9 +951,9 @@
hr = deviceContext->CreateEffect(CLSID_D2D1Shadow, &shadowEffect);
RELEASE_ASSERT(SUCCEEDED(hr));
- shadowEffect->SetInput(0, bitmap.get());
- shadowEffect->SetValue(D2D1_SHADOW_PROP_COLOR, static_cast<D2D1_VECTOR_4F>(m_state.shadowColor));
- shadowEffect->SetValue(D2D1_SHADOW_PROP_BLUR_STANDARD_DEVIATION, m_state.shadowBlur);
+ shadowEffect->SetInput(0, bitmap);
+ shadowEffect->SetValue(D2D1_SHADOW_PROP_COLOR, static_cast<D2D1_VECTOR_4F>(shadowColor));
+ shadowEffect->SetValue(D2D1_SHADOW_PROP_BLUR_STANDARD_DEVIATION, shadowBlur);
COMPtr<ID2D1Effect> transformEffect;
hr = deviceContext->CreateEffect(CLSID_D2D12DAffineTransform, &transformEffect);
@@ -956,7 +961,7 @@
transformEffect->SetInputEffect(0, shadowEffect.get());
- auto translation = D2D1::Matrix3x2F::Translation(m_state.shadowOffset.width(), m_state.shadowOffset.height());
+ auto translation = D2D1::Matrix3x2F::Translation(shadowOffset.width(), shadowOffset.height());
transformEffect->SetValue(D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX, translation);
COMPtr<ID2D1Effect> compositor;
@@ -964,7 +969,7 @@
RELEASE_ASSERT(SUCCEEDED(hr));
compositor->SetInputEffect(0, transformEffect.get());
- compositor->SetInput(1, bitmap.get());
+ compositor->SetInput(1, bitmap);
// Flip the context
D2D1_MATRIX_3X2_F ctm;
@@ -976,6 +981,27 @@
deviceContext->DrawImage(compositor.get(), D2D1_INTERPOLATION_MODE_LINEAR);
}
+void GraphicsContext::drawWithShadow(const FloatRect& boundingRect, const std::function<void(ID2D1RenderTarget*)>& drawCommands)
+{
+ auto context = platformContext();
+
+ // Render the current geometry to a bitmap context
+ COMPtr<ID2D1BitmapRenderTarget> bitmapTarget;
+ HRESULT hr = context->CreateCompatibleRenderTarget(&bitmapTarget);
+ RELEASE_ASSERT(SUCCEEDED(hr));
+
+ bitmapTarget->BeginDraw();
+ drawCommands(bitmapTarget.get());
+ hr = bitmapTarget->EndDraw();
+ RELEASE_ASSERT(SUCCEEDED(hr));
+
+ COMPtr<ID2D1Bitmap> bitmap;
+ hr = bitmapTarget->GetBitmap(&bitmap);
+ RELEASE_ASSERT(SUCCEEDED(hr));
+
+ drawWithShadowHelper(context, bitmap.get(), m_state.shadowColor, m_state.shadowOffset, m_state.shadowBlur);
+}
+
void GraphicsContext::fillPath(const Path& path)
{
if (paintingDisabled() || path.isEmpty())
@@ -1335,6 +1361,19 @@
return enclosingIntRect(clipBounds);
}
+void GraphicsContextPlatformPrivate::beginTransparencyLayer(float opacity)
+{
+ TransparencyLayerState transparencyLayer;
+ transparencyLayer.opacity = opacity;
+
+ HRESULT hr = m_renderTarget->CreateCompatibleRenderTarget(&transparencyLayer.renderTarget);
+ RELEASE_ASSERT(SUCCEEDED(hr));
+ m_transparencyLayerStack.append(WTFMove(transparencyLayer));
+
+ m_transparencyLayerStack.last().renderTarget->BeginDraw();
+ m_transparencyLayerStack.last().renderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));
+}
+
void GraphicsContext::beginPlatformTransparencyLayer(float opacity)
{
if (paintingDisabled())
@@ -1344,17 +1383,52 @@
save();
- notImplemented();
+ m_state.alpha = opacity;
+
+ m_data->beginTransparencyLayer(opacity);
}
+void GraphicsContextPlatformPrivate::endTransparencyLayer()
+{
+ auto currentLayer = m_transparencyLayerStack.takeLast();
+ auto renderTarget = currentLayer.renderTarget;
+ if (!renderTarget)
+ return;
+
+ HRESULT hr = renderTarget->EndDraw();
+ RELEASE_ASSERT(SUCCEEDED(hr));
+
+ COMPtr<ID2D1Bitmap> bitmap;
+ hr = renderTarget->GetBitmap(&bitmap);
+ RELEASE_ASSERT(SUCCEEDED(hr));
+
+ auto context = this->renderTarget();
+
+ if (currentLayer.hasShadow)
+ drawWithShadowHelper(context, bitmap.get(), currentLayer.shadowColor, currentLayer.shadowOffset, currentLayer.shadowBlur);
+ else {
+ COMPtr<ID2D1BitmapBrush> bitmapBrush;
+ auto bitmapBrushProperties = D2D1::BitmapBrushProperties();
+ auto brushProperties = D2D1::BrushProperties();
+ HRESULT hr = context->CreateBitmapBrush(bitmap.get(), bitmapBrushProperties, brushProperties, &bitmapBrush);
+ RELEASE_ASSERT(SUCCEEDED(hr));
+
+ auto size = bitmap->GetSize();
+ auto rectInDIP = D2D1::RectF(0, 0, size.width, size.height);
+ context->FillRectangle(rectInDIP, bitmapBrush.get());
+ }
+}
+
void GraphicsContext::endPlatformTransparencyLayer()
{
if (paintingDisabled())
return;
+ m_data->endTransparencyLayer();
+
ASSERT(!isRecording());
- notImplemented();
+ m_state.alpha = m_data->currentGlobalAlpha();
restore();
}
@@ -1417,7 +1491,7 @@
if (rectToClear.contains(renderTargetRect)) {
renderTarget->SetTags(1, __LINE__);
- renderTarget->Clear();
+ renderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));
return;
}
@@ -1426,7 +1500,7 @@
renderTarget->SetTags(1, __LINE__);
rectToClear.intersect(renderTargetRect);
- renderTarget->FillRectangle(rectToClear, solidFillBrush());
+ renderTarget->FillRectangle(rectToClear, brushWithColor(Color(D2D1::ColorF(0, 0, 0, 0))));
});
}
@@ -1789,9 +1863,13 @@
platformContext()->SetTextAntialiasMode(fontSmoothingMode);
}
-void GraphicsContext::setPlatformAlpha(float)
+void GraphicsContext::setPlatformAlpha(float alpha)
{
- /* No-op on this platform */
+ if (paintingDisabled())
+ return;
+
+ ASSERT(m_state.alpha == alpha);
+ m_data->setAlpha(alpha);
}
void GraphicsContext::setPlatformCompositeOperation(CompositeOperator mode, BlendMode blendMode)
Modified: trunk/Source/WebCore/platform/graphics/win/GraphicsContextPlatformPrivateDirect2D.h (208572 => 208573)
--- trunk/Source/WebCore/platform/graphics/win/GraphicsContextPlatformPrivateDirect2D.h 2016-11-11 00:49:06 UTC (rev 208572)
+++ trunk/Source/WebCore/platform/graphics/win/GraphicsContextPlatformPrivateDirect2D.h 2016-11-11 00:59:53 UTC (rev 208573)
@@ -44,6 +44,9 @@
enum Direct2DLayerType { AxisAlignedClip, LayerClip };
+ void beginTransparencyLayer(float opacity);
+ void endTransparencyLayer();
+
void clip(const FloatRect&);
void clip(const Path&);
void clip(ID2D1Geometry*);
@@ -68,8 +71,9 @@
void setPatternOffset(float);
void setStrokeThickness(float);
void setDashes(const DashArray&);
+ void setAlpha(float);
- ID2D1RenderTarget* renderTarget() { return m_renderTarget.get(); }
+ ID2D1RenderTarget* renderTarget();
ID2D1Layer* clipLayer() const { return m_renderStates.last().m_activeLayer.get(); }
ID2D1StrokeStyle* strokeStyle();
@@ -86,6 +90,8 @@
COMPtr<ID2D1BitmapBrush> m_patternStrokeBrush;
COMPtr<ID2D1BitmapBrush> m_patternFillBrush;
+ float currentGlobalAlpha() const;
+
private:
void recomputeStrokeStyle();
@@ -103,15 +109,27 @@
Vector<RenderState> m_renderStates;
+ struct TransparencyLayerState {
+ COMPtr<ID2D1BitmapRenderTarget> renderTarget;
+ Color shadowColor;
+ FloatSize shadowOffset;
+ float opacity { 1.0 };
+ float shadowBlur { 0 };
+ bool hasShadow { false };
+ };
+ Vector<TransparencyLayerState> m_transparencyLayerStack;
+
D2D1_CAP_STYLE m_lineCap { D2D1_CAP_STYLE_FLAT };
D2D1_LINE_JOIN m_lineJoin { D2D1_LINE_JOIN_MITER };
StrokeStyle m_strokeStyle { SolidStroke };
DashArray m_dashes;
+
float m_miterLimit { 1.0f };
float m_dashOffset { 0 };
float m_patternWidth { 1.0f };
float m_patternOffset { 0 };
float m_strokeThickness { 0 };
+ float m_alpha { 1.0 };
};
class D2DContextStateSaver {