Log Message
[Win][Direct2D] Implement dashed and dotted border line drawing https://bugs.webkit.org/show_bug.cgi?id=163235
Reviewed by Alex Christensen. Covered by existing fast/border tests. * platform/graphics/GraphicsContext.cpp: Use custom 'setPlatformStrokeStyle' for D2D. * platform/graphics/Path.cpp: (WebCore::Path::length): Don't use default implementation for Direct2D. * platform/graphics/win/GraphicsContextDirect2D.cpp: (WebCore::GraphicsContextPlatformPrivate::brushWithColor): Initialize pointer to nullptr. (WebCore::GraphicsContext::drawRect): Use proper stroke style. (WebCore::GraphicsContextPlatformPrivate::setLineCap): Added. (WebCore::GraphicsContextPlatformPrivate::setLineJoin): Added. (WebCore::GraphicsContextPlatformPrivate::setStrokeStyle): Added. (WebCore::GraphicsContextPlatformPrivate::setMiterLimit): Added. (WebCore::GraphicsContextPlatformPrivate::setDashOffset): Added. (WebCore::GraphicsContextPlatformPrivate::setPatternWidth): Added. (WebCore::GraphicsContextPlatformPrivate::setPatternOffset): Added. (WebCore::GraphicsContextPlatformPrivate::setStrokeThickness): Added. (WebCore::GraphicsContextPlatformPrivate::setDashes): Added. (WebCore::GraphicsContextPlatformPrivate::recomputeStrokeStyle): Added. (WebCore::GraphicsContextPlatformPrivate::strokeStyle): Added. (WebCore::GraphicsContext::drawLine): Use proper stroke style. (WebCore::GraphicsContext::drawEllipse): Ditto. (WebCore::GraphicsContext::drawPath): Ditto. (WebCore::GraphicsContext::strokePath): Ditto. (WebCore::GraphicsContext::setPlatformStrokeStyle): Added. (WebCore::GraphicsContext::setMiterLimit): Tell D2D context about miter limit. (WebCore::GraphicsContext::setLineCap): Ditto for line cap. (WebCore::GraphicsContext::setLineDash): Ditto for dashes. (WebCore::GraphicsContext::setLineJoin): Ditto for join style. (WebCore::GraphicsContext::setPlatformStrokeThickness): Ditto for stroke thickness. (WebCore::GraphicsContext::platformStrokeEllipse): Use proper stroke style. * platform/graphics/win/GraphicsContextPlatformPrivateDirect2D.h: * platform/graphics/win/PathDirect2D.cpp: (WebCore::Path::currentPoint): Zero-initialize a value. (WebCore::Path::length): Added.
Modified Paths
- trunk/Source/WebCore/ChangeLog
- trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp
- trunk/Source/WebCore/platform/graphics/Path.cpp
- trunk/Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp
- trunk/Source/WebCore/platform/graphics/win/GraphicsContextPlatformPrivateDirect2D.h
- trunk/Source/WebCore/platform/graphics/win/PathDirect2D.cpp
Diff
Modified: trunk/Source/WebCore/ChangeLog (207019 => 207020)
--- trunk/Source/WebCore/ChangeLog 2016-10-10 20:57:37 UTC (rev 207019)
+++ trunk/Source/WebCore/ChangeLog 2016-10-10 20:59:48 UTC (rev 207020)
@@ -1,3 +1,45 @@
+2016-10-10 Brent Fulgham <bfulg...@apple.com>
+
+ [Win][Direct2D] Implement dashed and dotted border line drawing
+ https://bugs.webkit.org/show_bug.cgi?id=163235
+
+ Reviewed by Alex Christensen.
+
+ Covered by existing fast/border tests.
+
+ * platform/graphics/GraphicsContext.cpp: Use custom 'setPlatformStrokeStyle' for D2D.
+ * platform/graphics/Path.cpp:
+ (WebCore::Path::length): Don't use default implementation for Direct2D.
+ * platform/graphics/win/GraphicsContextDirect2D.cpp:
+ (WebCore::GraphicsContextPlatformPrivate::brushWithColor): Initialize pointer to nullptr.
+ (WebCore::GraphicsContext::drawRect): Use proper stroke style.
+ (WebCore::GraphicsContextPlatformPrivate::setLineCap): Added.
+ (WebCore::GraphicsContextPlatformPrivate::setLineJoin): Added.
+ (WebCore::GraphicsContextPlatformPrivate::setStrokeStyle): Added.
+ (WebCore::GraphicsContextPlatformPrivate::setMiterLimit): Added.
+ (WebCore::GraphicsContextPlatformPrivate::setDashOffset): Added.
+ (WebCore::GraphicsContextPlatformPrivate::setPatternWidth): Added.
+ (WebCore::GraphicsContextPlatformPrivate::setPatternOffset): Added.
+ (WebCore::GraphicsContextPlatformPrivate::setStrokeThickness): Added.
+ (WebCore::GraphicsContextPlatformPrivate::setDashes): Added.
+ (WebCore::GraphicsContextPlatformPrivate::recomputeStrokeStyle): Added.
+ (WebCore::GraphicsContextPlatformPrivate::strokeStyle): Added.
+ (WebCore::GraphicsContext::drawLine): Use proper stroke style.
+ (WebCore::GraphicsContext::drawEllipse): Ditto.
+ (WebCore::GraphicsContext::drawPath): Ditto.
+ (WebCore::GraphicsContext::strokePath): Ditto.
+ (WebCore::GraphicsContext::setPlatformStrokeStyle): Added.
+ (WebCore::GraphicsContext::setMiterLimit): Tell D2D context about miter limit.
+ (WebCore::GraphicsContext::setLineCap): Ditto for line cap.
+ (WebCore::GraphicsContext::setLineDash): Ditto for dashes.
+ (WebCore::GraphicsContext::setLineJoin): Ditto for join style.
+ (WebCore::GraphicsContext::setPlatformStrokeThickness): Ditto for stroke thickness.
+ (WebCore::GraphicsContext::platformStrokeEllipse): Use proper stroke style.
+ * platform/graphics/win/GraphicsContextPlatformPrivateDirect2D.h:
+ * platform/graphics/win/PathDirect2D.cpp:
+ (WebCore::Path::currentPoint): Zero-initialize a value.
+ (WebCore::Path::length): Added.
+
2016-10-10 Chris Dumez <cdu...@apple.com>
Update ProgressEvent to stop using legacy [ConstructorTemplate=Event]
Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp (207019 => 207020)
--- trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp 2016-10-10 20:57:37 UTC (rev 207019)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp 2016-10-10 20:59:48 UTC (rev 207020)
@@ -964,7 +964,7 @@
}
#endif
-#if !USE(CAIRO)
+#if !USE(CAIRO) && !USE(DIRECT2D)
void GraphicsContext::setPlatformStrokeStyle(StrokeStyle)
{
}
Modified: trunk/Source/WebCore/platform/graphics/Path.cpp (207019 => 207020)
--- trunk/Source/WebCore/platform/graphics/Path.cpp 2016-10-10 20:57:37 UTC (rev 207019)
+++ trunk/Source/WebCore/platform/graphics/Path.cpp 2016-10-10 20:59:48 UTC (rev 207020)
@@ -40,6 +40,7 @@
namespace WebCore {
+#if !USE(DIRECT2D)
float Path::length() const
{
PathTraversalState traversalState(PathTraversalState::Action::TotalLength);
@@ -50,6 +51,7 @@
return traversalState.totalLength();
}
+#endif
PathTraversalState Path::traversalStateAtLength(float length, bool& success) const
{
@@ -116,7 +118,7 @@
}
if (strategy == PreferNativeRoundedRect) {
-#if USE(CG)
+#if USE(CG) || USE(DIRECT2D)
platformAddPathForRoundedRect(rect, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight());
return;
#endif
Modified: trunk/Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp (207019 => 207020)
--- trunk/Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp 2016-10-10 20:57:37 UTC (rev 207019)
+++ trunk/Source/WebCore/platform/graphics/win/GraphicsContextDirect2D.cpp 2016-10-10 20:59:48 UTC (rev 207020)
@@ -274,7 +274,7 @@
}
auto existingBrush = m_solidColoredBrushCache.ensure(colorKey, [this, color] {
- ID2D1SolidColorBrush* colorBrush;
+ ID2D1SolidColorBrush* colorBrush = nullptr;
m_renderTarget->CreateSolidColorBrush(color, &colorBrush);
return colorBrush;
});
@@ -467,11 +467,149 @@
drawWithoutShadow(rect, [this, rect](ID2D1RenderTarget* renderTarget) {
const D2D1_RECT_F d2dRect = rect;
- renderTarget->DrawRectangle(&d2dRect, solidStrokeBrush(), strokeThickness());
renderTarget->FillRectangle(&d2dRect, solidFillBrush());
+ renderTarget->DrawRectangle(&d2dRect, solidStrokeBrush(), strokeThickness(), m_data->strokeStyle());
});
}
+void GraphicsContextPlatformPrivate::setLineCap(LineCap cap)
+{
+ if (m_lineCap == cap)
+ return;
+
+ D2D1_CAP_STYLE capStyle = D2D1_CAP_STYLE_FLAT;
+ switch (cap) {
+ case RoundCap:
+ capStyle = D2D1_CAP_STYLE_ROUND;
+ break;
+ case SquareCap:
+ capStyle = D2D1_CAP_STYLE_SQUARE;
+ break;
+ case ButtCap:
+ default:
+ capStyle = D2D1_CAP_STYLE_FLAT;
+ break;
+ }
+
+ m_lineCap = capStyle;
+ m_strokeSyleIsDirty = true;
+}
+
+void GraphicsContextPlatformPrivate::setLineJoin(LineJoin join)
+{
+ if (m_lineJoin == join)
+ return;
+
+ D2D1_LINE_JOIN joinStyle = D2D1_LINE_JOIN_MITER;
+ switch (join) {
+ case RoundJoin:
+ joinStyle = D2D1_LINE_JOIN_ROUND;
+ break;
+ case BevelJoin:
+ joinStyle = D2D1_LINE_JOIN_BEVEL;
+ break;
+ case MiterJoin:
+ default:
+ joinStyle = D2D1_LINE_JOIN_MITER;
+ break;
+ }
+
+ m_lineJoin = joinStyle;
+ m_strokeSyleIsDirty = true;
+}
+
+void GraphicsContextPlatformPrivate::setStrokeStyle(StrokeStyle strokeStyle)
+{
+ if (m_strokeStyle == strokeStyle)
+ return;
+
+ m_strokeStyle = strokeStyle;
+ m_strokeSyleIsDirty = true;
+}
+
+void GraphicsContextPlatformPrivate::setMiterLimit(float miterLimit)
+{
+ if (WTF::areEssentiallyEqual(miterLimit, m_miterLimit))
+ return;
+
+ m_miterLimit = miterLimit;
+ m_strokeSyleIsDirty = true;
+}
+
+void GraphicsContextPlatformPrivate::setDashOffset(float dashOffset)
+{
+ if (WTF::areEssentiallyEqual(dashOffset, m_dashOffset))
+ return;
+
+ m_dashOffset = dashOffset;
+ m_strokeSyleIsDirty = true;
+}
+
+void GraphicsContextPlatformPrivate::setPatternWidth(float patternWidth)
+{
+ if (WTF::areEssentiallyEqual(patternWidth, m_patternWidth))
+ return;
+
+ m_patternWidth = patternWidth;
+ m_strokeSyleIsDirty = true;
+}
+
+void GraphicsContextPlatformPrivate::setPatternOffset(float patternOffset)
+{
+ if (WTF::areEssentiallyEqual(patternOffset, m_patternOffset))
+ return;
+
+ m_patternOffset = patternOffset;
+ m_strokeSyleIsDirty = true;
+}
+
+void GraphicsContextPlatformPrivate::setStrokeThickness(float thickness)
+{
+ if (WTF::areEssentiallyEqual(thickness, m_strokeThickness))
+ return;
+
+ m_strokeThickness = thickness;
+ m_strokeSyleIsDirty = true;
+}
+
+void GraphicsContextPlatformPrivate::setDashes(const DashArray& dashes)
+{
+ if (m_dashes == dashes)
+ return;
+
+ m_dashes = dashes;
+ m_strokeSyleIsDirty = true;
+}
+
+void GraphicsContextPlatformPrivate::recomputeStrokeStyle()
+{
+ if (!m_strokeSyleIsDirty)
+ return;
+
+ m_d2dStrokeStyle = nullptr;
+
+ if ((m_strokeStyle != SolidStroke) && (m_strokeStyle != NoStroke)) {
+ float patternOffset = m_patternOffset / m_strokeThickness;
+
+ DashArray dashes = m_dashes;
+
+ // In Direct2D, dashes and dots are defined in terms of the ratio of the dash length to the line thickness.
+ for (auto& dash : dashes)
+ dash /= m_strokeThickness;
+
+ auto strokeStyleProperties = D2D1::StrokeStyleProperties(m_lineCap, m_lineCap, m_lineCap, m_lineJoin, m_strokeThickness, D2D1_DASH_STYLE_CUSTOM, patternOffset);
+ GraphicsContext::systemFactory()->CreateStrokeStyle(&strokeStyleProperties, dashes.data(), dashes.size(), &m_d2dStrokeStyle);
+ }
+
+ m_strokeSyleIsDirty = false;
+}
+
+ID2D1StrokeStyle* GraphicsContextPlatformPrivate::strokeStyle()
+{
+ recomputeStrokeStyle();
+ return m_d2dStrokeStyle.get();
+}
+
// This is only used to draw borders.
void GraphicsContext::drawLine(const FloatPoint& point1, const FloatPoint& point2)
{
@@ -513,6 +651,12 @@
const float dashes[2] = { patternWidth, patternWidth };
auto strokeStyleProperties = D2D1::StrokeStyleProperties();
GraphicsContext::systemFactory()->CreateStrokeStyle(&strokeStyleProperties, dashes, ARRAYSIZE(dashes), &d2dStrokeStyle);
+
+ m_data->setPatternWidth(patternWidth);
+ m_data->setPatternOffset(patternOffset);
+ m_data->setDashes(DashArray(2, patternWidth));
+
+ d2dStrokeStyle = m_data->strokeStyle();
}
auto centeredPoints = centerLineAndCutOffCorners(isVerticalLine, cornerWidth, point1, point2);
@@ -547,7 +691,7 @@
drawWithoutShadow(rect, [this, ellipse](ID2D1RenderTarget* renderTarget) {
renderTarget->FillEllipse(&ellipse, solidFillBrush());
- renderTarget->DrawEllipse(&ellipse, solidStrokeBrush(), strokeThickness());
+ renderTarget->DrawEllipse(&ellipse, solidStrokeBrush(), strokeThickness(), m_data->strokeStyle());
});
}
@@ -603,7 +747,7 @@
auto rect = path.fastBoundingRect();
drawWithoutShadow(rect, [this, &path](ID2D1RenderTarget* renderTarget) {
- renderTarget->DrawGeometry(path.platformPath(), solidStrokeBrush());
+ renderTarget->DrawGeometry(path.platformPath(), solidStrokeBrush(), strokeThickness(), m_data->strokeStyle());
});
}
@@ -768,7 +912,7 @@
FloatRect contextRect(FloatPoint(), context->GetSize());
drawWithoutShadow(contextRect, [this, &path](ID2D1RenderTarget* renderTarget) {
- renderTarget->DrawGeometry(path.platformPath(), solidStrokeBrush(), strokeThickness());
+ renderTarget->DrawGeometry(path.platformPath(), solidStrokeBrush(), strokeThickness(), m_data->strokeStyle());
});
}
@@ -1089,6 +1233,14 @@
notImplemented();
}
+void GraphicsContext::setPlatformStrokeStyle(StrokeStyle style)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->setStrokeStyle(style);
+}
+
void GraphicsContext::setMiterLimit(float limit)
{
if (paintingDisabled())
@@ -1100,7 +1252,7 @@
return;
}
- notImplemented();
+ m_data->setMiterLimit(limit);
}
void GraphicsContext::clearRect(const FloatRect& rect)
@@ -1135,8 +1287,15 @@
void GraphicsContext::setLineCap(LineCap cap)
{
- (void)cap;
- notImplemented();
+ if (paintingDisabled())
+ return;
+
+ if (isRecording()) {
+ m_displayListRecorder->setLineCap(cap);
+ return;
+ }
+
+ m_data->setLineCap(cap);
}
void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
@@ -1157,7 +1316,8 @@
dashOffset = fmod(dashOffset, length) + length;
}
- notImplemented();
+ m_data->setDashes(dashes);
+ m_data->setDashOffset(dashOffset);
}
void GraphicsContext::setLineJoin(LineJoin join)
@@ -1170,7 +1330,7 @@
return;
}
- notImplemented();
+ m_data->setLineJoin(join);
}
void GraphicsContext::canvasClip(const Path& path, WindRule fillRule)
@@ -1414,8 +1574,8 @@
void GraphicsContext::setPlatformStrokeThickness(float thickness)
{
- // This is a no-op on Windows. We fill using the GraphicsContextState::strokeThickness member.
ASSERT(m_state.strokeThickness == thickness);
+ m_data->setStrokeThickness(thickness);
}
void GraphicsContext::setPlatformFillColor(const Color& color)
@@ -1616,7 +1776,7 @@
platformContext()->SetTags(1, __LINE__);
drawWithoutShadow(ellipse, [this, d2dEllipse](ID2D1RenderTarget* renderTarget) {
- renderTarget->DrawEllipse(&d2dEllipse, solidStrokeBrush(), strokeThickness());
+ renderTarget->DrawEllipse(&d2dEllipse, solidStrokeBrush(), strokeThickness(), m_data->strokeStyle());
});
}
Modified: trunk/Source/WebCore/platform/graphics/win/GraphicsContextPlatformPrivateDirect2D.h (207019 => 207020)
--- trunk/Source/WebCore/platform/graphics/win/GraphicsContextPlatformPrivateDirect2D.h 2016-10-10 20:57:37 UTC (rev 207019)
+++ trunk/Source/WebCore/platform/graphics/win/GraphicsContextPlatformPrivateDirect2D.h 2016-10-10 20:59:48 UTC (rev 207020)
@@ -59,8 +59,19 @@
void concatCTM(const AffineTransform&);
void setCTM(const AffineTransform&);
+ void setLineCap(LineCap);
+ void setLineJoin(LineJoin);
+ void setStrokeStyle(StrokeStyle);
+ void setMiterLimit(float);
+ void setDashOffset(float);
+ void setPatternWidth(float);
+ void setPatternOffset(float);
+ void setStrokeThickness(float);
+ void setDashes(const DashArray&);
+
ID2D1RenderTarget* renderTarget() { return m_renderTarget.get(); }
ID2D1Layer* clipLayer() const { return m_renderStates.last().m_activeLayer.get(); }
+ ID2D1StrokeStyle* strokeStyle();
COMPtr<ID2D1SolidColorBrush> brushWithColor(const D2D1_COLOR_F&);
@@ -69,15 +80,19 @@
D2D1_COMPOSITE_MODE m_compositeMode { D2D1_COMPOSITE_MODE_SOURCE_OVER };
bool m_shouldIncludeChildWindows { false };
bool m_didBeginDraw { false };
+ bool m_strokeSyleIsDirty { false };
COMPtr<ID2D1SolidColorBrush> m_solidStrokeBrush;
COMPtr<ID2D1SolidColorBrush> m_solidFillBrush;
private:
+ void recomputeStrokeStyle();
+
COMPtr<ID2D1RenderTarget> m_renderTarget;
HashMap<RGBA32, COMPtr<ID2D1SolidColorBrush>> m_solidColoredBrushCache;
COMPtr<ID2D1SolidColorBrush> m_whiteBrush;
COMPtr<ID2D1SolidColorBrush> m_zeroBrush;
+ COMPtr<ID2D1StrokeStyle> m_d2dStrokeStyle;
struct RenderState {
COMPtr<ID2D1DrawingStateBlock> m_drawingStateBlock;
@@ -86,6 +101,16 @@
};
Vector<RenderState> m_renderStates;
+
+ 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 };
};
class D2DContextStateSaver {
Modified: trunk/Source/WebCore/platform/graphics/win/PathDirect2D.cpp (207019 => 207020)
--- trunk/Source/WebCore/platform/graphics/win/PathDirect2D.cpp 2016-10-10 20:57:37 UTC (rev 207019)
+++ trunk/Source/WebCore/platform/graphics/win/PathDirect2D.cpp 2016-10-10 20:59:48 UTC (rev 207020)
@@ -490,7 +490,7 @@
if (isNull())
return FloatPoint();
- float length;
+ float length = 0;
HRESULT hr = m_path->ComputeLength(nullptr, &length);
if (!SUCCEEDED(hr))
return FloatPoint();
@@ -504,6 +504,16 @@
return point;
}
+float Path::length() const
+{
+ float length = 0;
+ HRESULT hr = m_path->ComputeLength(nullptr, &length);
+ if (!SUCCEEDED(hr))
+ return 0;
+
+ return length;
+}
+
void Path::apply(const PathApplierFunction& function) const
{
if (isNull())
_______________________________________________ webkit-changes mailing list webkit-changes@lists.webkit.org https://lists.webkit.org/mailman/listinfo/webkit-changes