diff options
Diffstat (limited to 'win32')
| -rw-r--r-- | win32/PlatWin.cxx | 103 | 
1 files changed, 103 insertions, 0 deletions
| diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index eac743ef3..673df5c2b 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -505,6 +505,7 @@ public:  	void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) override;  	void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) override;  	void Ellipse(PRectangle rc, FillStroke fillStroke) override; +	void Stadium(PRectangle rc, FillStroke fillStroke, Ends ends) override;  	void Copy(PRectangle rc, Point from, Surface &surfaceSource) override;  	std::unique_ptr<IScreenLineLayout> Layout(const IScreenLine *screenLine) override; @@ -1083,6 +1084,11 @@ void SurfaceGDI::Ellipse(PRectangle rc, FillStroke fillStroke) {  	::Ellipse(hdc, rcw.left, rcw.top, rcw.right, rcw.bottom);  } +void SurfaceGDI::Stadium(PRectangle rc, FillStroke fillStroke, [[maybe_unused]] Ends ends) { +	// TODO: Implement properly - the rectangle is just a placeholder +	RectangleDraw(rc, fillStroke); +} +  void SurfaceGDI::Copy(PRectangle rc, Point from, Surface &surfaceSource) {  	::BitBlt(hdc,  		static_cast<int>(rc.left), static_cast<int>(rc.top), @@ -1436,6 +1442,7 @@ public:  	void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) override;  	void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) override;  	void Ellipse(PRectangle rc, FillStroke fillStroke) override; +	void Stadium(PRectangle rc, FillStroke fillStroke, Ends ends) override;  	void Copy(PRectangle rc, Point from, Surface &surfaceSource) override;  	std::unique_ptr<IScreenLineLayout> Layout(const IScreenLine *screenLine) override; @@ -1999,6 +2006,102 @@ void SurfaceD2D::Ellipse(PRectangle rc, FillStroke fillStroke) {  	pRenderTarget->DrawEllipse(ellipseOutline, pBrush, fillStroke.stroke.width);  } +void SurfaceD2D::Stadium(PRectangle rc, FillStroke fillStroke, Ends ends) { +	if (!pRenderTarget) +		return; +	if (rc.Width() < rc.Height()) { +		// Can't draw nice ends so just draw a rectangle +		RectangleDraw(rc, fillStroke); +		return; +	} +	const float radius = rc.Height() / 2.0f; +	const float radiusFill = radius - fillStroke.stroke.width; +	const XYPOSITION halfStroke = fillStroke.stroke.width / 2.0f; +	if (ends == Surface::Ends::semiCircles) { +		const D2D1_RECT_F rect = { rc.left, rc.top, rc.right, rc.bottom }; +		D2D1_ROUNDED_RECT roundedRectFill = { RectangleInset(rect, fillStroke.stroke.width), +			radiusFill, radiusFill }; +		D2DPenColourAlpha(fillStroke.fill.colour); +		pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush); + +		D2D1_ROUNDED_RECT roundedRect = { RectangleInset(rect, halfStroke), +			radius, radius }; +		D2DPenColourAlpha(fillStroke.stroke.colour); +		pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush, fillStroke.stroke.width); +	} else { +		const Ends leftSide = static_cast<Ends>(static_cast<int>(ends) & 0xf); +		const Ends rightSide = static_cast<Ends>(static_cast<int>(ends) & 0xf0); +		PRectangle rcInner = rc; +		rcInner.left += radius; +		rcInner.right -= radius; +		ID2D1PathGeometry *pathGeometry = nullptr; +		const HRESULT hrGeometry = pD2DFactory->CreatePathGeometry(&pathGeometry); +		if (FAILED(hrGeometry) || !pathGeometry) +			return; +		ID2D1GeometrySink *pSink = nullptr; +		const HRESULT hrSink = pathGeometry->Open(&pSink); +		if (SUCCEEDED(hrSink) && pSink) { +			switch (leftSide) { +				case Ends::leftFlat: +					pSink->BeginFigure(D2D1::Point2F(rc.left + halfStroke, rc.top + halfStroke), D2D1_FIGURE_BEGIN_FILLED); +					pSink->AddLine(D2D1::Point2F(rc.left + halfStroke, rc.bottom - halfStroke)); +					break; +				case Ends::leftAngle: +					pSink->BeginFigure(D2D1::Point2F(rcInner.left + halfStroke, rc.top + halfStroke), D2D1_FIGURE_BEGIN_FILLED); +					pSink->AddLine(D2D1::Point2F(rc.left + halfStroke, rc.Centre().y)); +					pSink->AddLine(D2D1::Point2F(rcInner.left + halfStroke, rc.bottom - halfStroke)); +					break; +				case Ends::semiCircles: +				default: { +						pSink->BeginFigure(D2D1::Point2F(rcInner.left + halfStroke, rc.top + halfStroke), D2D1_FIGURE_BEGIN_FILLED); +						D2D1_ARC_SEGMENT segment{}; +						segment.point = D2D1::Point2F(rcInner.left + halfStroke, rc.bottom - halfStroke); +						segment.size = D2D1::SizeF(radiusFill, radiusFill); +						segment.rotationAngle = 0.0f; +						segment.sweepDirection = D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE; +						segment.arcSize = D2D1_ARC_SIZE_SMALL; +						pSink->AddArc(segment); +					} +					break; +			} + +			switch (rightSide) { +			case Ends::rightFlat: +				pSink->AddLine(D2D1::Point2F(rc.right - halfStroke, rc.bottom - halfStroke)); +				pSink->AddLine(D2D1::Point2F(rc.right - halfStroke, rc.top + halfStroke)); +				break; +			case Ends::rightAngle: +				pSink->AddLine(D2D1::Point2F(rcInner.right - halfStroke, rc.bottom - halfStroke)); +				pSink->AddLine(D2D1::Point2F(rc.right - halfStroke, rc.Centre().y)); +				pSink->AddLine(D2D1::Point2F(rcInner.right - halfStroke, rc.top + halfStroke)); +				break; +			case Ends::semiCircles: +			default: { +					pSink->AddLine(D2D1::Point2F(rcInner.right - halfStroke, rc.bottom - halfStroke)); +					D2D1_ARC_SEGMENT segment{}; +					segment.point = D2D1::Point2F(rcInner.right - halfStroke, rc.top + halfStroke); +					segment.size = D2D1::SizeF(radiusFill, radiusFill); +					segment.rotationAngle = 0.0f; +					segment.sweepDirection = D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE; +					segment.arcSize = D2D1_ARC_SIZE_SMALL; +					pSink->AddArc(segment); +				} +				break; +			} + +			pSink->EndFigure(D2D1_FIGURE_END_CLOSED); + +			pSink->Close(); +		} +		ReleaseUnknown(pSink); +		D2DPenColourAlpha(fillStroke.fill.colour); +		pRenderTarget->FillGeometry(pathGeometry, pBrush); +		D2DPenColourAlpha(fillStroke.stroke.colour); +		pRenderTarget->DrawGeometry(pathGeometry, pBrush, fillStroke.stroke.width); +		ReleaseUnknown(pathGeometry); +	} +} +  void SurfaceD2D::Copy(PRectangle rc, Point from, Surface &surfaceSource) {  	SurfaceD2D &surfOther = dynamic_cast<SurfaceD2D &>(surfaceSource);  	ID2D1Bitmap *pBitmap = nullptr; | 
