aboutsummaryrefslogtreecommitdiffhomepage
path: root/win32/PlatWin.cxx
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2025-02-18 11:29:48 +1100
committerNeil <nyamatongwe@gmail.com>2025-02-18 11:29:48 +1100
commitbf1a0274c6f98748d5c720c3ed242f99c8fbee34 (patch)
treed6219e580c3c66000654070f2042b43f032ff7d9 /win32/PlatWin.cxx
parenta6278c653a6161ddf59274136c53997d1a966eaa (diff)
downloadscintilla-mirror-bf1a0274c6f98748d5c720c3ed242f99c8fbee34.tar.gz
Use ComPtr for geometric and graphic objects: brush, geometry, geometry sink,
stroke style, bitmap, and gradients to remove explicit release calls and possible leaks. Ensure HPEN and HBRUSH initialised. Not converting render targets, text formats or text layouts yet.
Diffstat (limited to 'win32/PlatWin.cxx')
-rw-r--r--win32/PlatWin.cxx158
1 files changed, 78 insertions, 80 deletions
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
index 2eb5d2fcd..969314b55 100644
--- a/win32/PlatWin.cxx
+++ b/win32/PlatWin.cxx
@@ -208,6 +208,8 @@ HRESULT CreateDCRenderTarget(const D2D1_RENDER_TARGET_PROPERTIES *renderTargetPr
return pD2DFactory->CreateDCRenderTarget(renderTargetProperties, dcRT.ReleaseAndGetAddressOf());
}
+namespace {
+
constexpr D2D_COLOR_F ColorFromColourAlpha(ColourRGBA colour) noexcept {
return D2D_COLOR_F{
colour.GetRedComponent(),
@@ -217,38 +219,49 @@ constexpr D2D_COLOR_F ColorFromColourAlpha(ColourRGBA colour) noexcept {
};
}
-using BrushSolid = std::unique_ptr<ID2D1SolidColorBrush, UnknownReleaser>;
+using BrushSolid = ComPtr<ID2D1SolidColorBrush>;
BrushSolid BrushSolidCreate(ID2D1RenderTarget *pTarget, COLORREF colour) noexcept {
- ID2D1SolidColorBrush *pBrush = nullptr;
+ BrushSolid brush;
const D2D_COLOR_F col = ColorFromColourAlpha(ColourRGBA::FromRGB(colour));
- const HRESULT hr = pTarget->CreateSolidColorBrush(col, &pBrush);
- if (FAILED(hr) || !pBrush) {
+ if (FAILED(pTarget->CreateSolidColorBrush(col, brush.GetAddressOf()))) {
return {};
}
- return BrushSolid(pBrush);
+ return brush;
}
-using Geometry = std::unique_ptr<ID2D1PathGeometry, UnknownReleaser>;
+using Geometry = ComPtr<ID2D1PathGeometry>;
Geometry GeometryCreate() noexcept {
- ID2D1PathGeometry *geometry = nullptr;
- const HRESULT hr = pD2DFactory->CreatePathGeometry(&geometry);
- if (FAILED(hr) || !geometry) {
+ Geometry geometry;
+ if (FAILED(pD2DFactory->CreatePathGeometry(geometry.GetAddressOf()))) {
return {};
}
- return Geometry(geometry);
+ return geometry;
}
-using GeometrySink = std::unique_ptr<ID2D1GeometrySink, UnknownReleaser>;
+using GeometrySink = ComPtr<ID2D1GeometrySink>;
GeometrySink GeometrySinkCreate(ID2D1PathGeometry *geometry) noexcept {
- ID2D1GeometrySink *sink = nullptr;
- const HRESULT hr = geometry->Open(&sink);
- if (FAILED(hr) || !sink) {
+ GeometrySink sink;
+ if (FAILED(geometry->Open(sink.GetAddressOf()))) {
return {};
}
- return GeometrySink(sink);
+ return sink;
+}
+
+using StrokeStyle = ComPtr<ID2D1StrokeStyle>;
+
+StrokeStyle StrokeStyleCreate(const D2D1_STROKE_STYLE_PROPERTIES &strokeStyleProperties) noexcept {
+ StrokeStyle strokeStyle;
+ const HRESULT hr = pD2DFactory->CreateStrokeStyle(
+ strokeStyleProperties, nullptr, 0, strokeStyle.GetAddressOf());
+ if (FAILED(hr)) {
+ return {};
+ }
+ return strokeStyle;
+}
+
}
#endif
@@ -902,7 +915,7 @@ void SurfaceGDI::FillRectangleAligned(PRectangle rc, Fill fill) {
}
void SurfaceGDI::FillRectangle(PRectangle rc, Surface &surfacePattern) {
- HBRUSH br;
+ HBRUSH br{};
if (SurfaceGDI *psgdi = dynamic_cast<SurfaceGDI *>(&surfacePattern); psgdi && psgdi->bitmap) {
br = ::CreatePatternBrush(psgdi->bitmap);
} else { // Something is wrong so display in red
@@ -1445,7 +1458,7 @@ class SurfaceD2D : public Surface, public ISetRenderingParams {
bool ownRenderTarget = false;
int clipsActive = 0;
- ID2D1SolidColorBrush *pBrush = nullptr;
+ BrushSolid pBrush = nullptr;
static constexpr FontQuality invalidFontQuality = FontQuality::QualityMask;
FontQuality fontQuality = invalidFontQuality;
@@ -1559,7 +1572,7 @@ SurfaceD2D::~SurfaceD2D() noexcept {
}
void SurfaceD2D::Clear() noexcept {
- ReleaseUnknown(pBrush);
+ pBrush = nullptr;
if (pRenderTarget) {
while (clipsActive) {
pRenderTarget->PopAxisAlignedClip();
@@ -1631,7 +1644,7 @@ void SurfaceD2D::D2DPenColourAlpha(ColourRGBA fore) noexcept {
} else {
const HRESULT hr = pRenderTarget->CreateSolidColorBrush(col, &pBrush);
if (!SUCCEEDED(hr)) {
- ReleaseUnknown(pBrush);
+ pBrush = nullptr;
}
}
}
@@ -1682,22 +1695,17 @@ void SurfaceD2D::LineDraw(Point start, Point end, Stroke stroke) {
strokeProps.dashOffset = 0;
// get the stroke style to apply
- ID2D1StrokeStyle *pStrokeStyle = nullptr;
- const HRESULT hr = pD2DFactory->CreateStrokeStyle(
- strokeProps, nullptr, 0, &pStrokeStyle);
- if (SUCCEEDED(hr)) {
+ if (const StrokeStyle pStrokeStyle = StrokeStyleCreate(strokeProps)) {
pRenderTarget->DrawLine(
DPointFromPoint(start),
- DPointFromPoint(end), pBrush, stroke.WidthF(), pStrokeStyle);
+ DPointFromPoint(end), pBrush.Get(), stroke.WidthF(), pStrokeStyle.Get());
}
-
- ReleaseUnknown(pStrokeStyle);
}
Geometry SurfaceD2D::GeometricFigure(const Point *pts, size_t npts, D2D1_FIGURE_BEGIN figureBegin) noexcept {
Geometry geometry = GeometryCreate();
if (geometry) {
- if (const GeometrySink sink = GeometrySinkCreate(geometry.get())) {
+ if (const GeometrySink sink = GeometrySinkCreate(geometry.Get())) {
sink->BeginFigure(DPointFromPoint(pts[0]), figureBegin);
for (size_t i = 1; i < npts; i++) {
sink->AddLine(DPointFromPoint(pts[i]));
@@ -1733,13 +1741,9 @@ void SurfaceD2D::PolyLine(const Point *pts, size_t npts, Stroke stroke) {
strokeProps.dashOffset = 0;
// get the stroke style to apply
- ID2D1StrokeStyle *pStrokeStyle = nullptr;
- const HRESULT hr = pD2DFactory->CreateStrokeStyle(
- strokeProps, nullptr, 0, &pStrokeStyle);
- if (SUCCEEDED(hr)) {
- pRenderTarget->DrawGeometry(geometry.get(), pBrush, stroke.WidthF(), pStrokeStyle);
+ if (const StrokeStyle pStrokeStyle = StrokeStyleCreate(strokeProps)) {
+ pRenderTarget->DrawGeometry(geometry.Get(), pBrush.Get(), stroke.WidthF(), pStrokeStyle.Get());
}
- ReleaseUnknown(pStrokeStyle);
}
void SurfaceD2D::Polygon(const Point *pts, size_t npts, FillStroke fillStroke) {
@@ -1749,9 +1753,9 @@ void SurfaceD2D::Polygon(const Point *pts, size_t npts, FillStroke fillStroke) {
PLATFORM_ASSERT(geometry);
if (geometry) {
D2DPenColourAlpha(fillStroke.fill.colour);
- pRenderTarget->FillGeometry(geometry.get(), pBrush);
+ pRenderTarget->FillGeometry(geometry.Get(), pBrush.Get());
D2DPenColourAlpha(fillStroke.stroke.colour);
- pRenderTarget->DrawGeometry(geometry.get(), pBrush, fillStroke.stroke.WidthF());
+ pRenderTarget->DrawGeometry(geometry.Get(), pBrush.Get(), fillStroke.stroke.WidthF());
}
}
}
@@ -1765,9 +1769,9 @@ void SurfaceD2D::RectangleDraw(PRectangle rc, FillStroke fillStroke) {
const D2D1_RECT_F rectOutline = RectangleInset(rect, halfStroke);
D2DPenColourAlpha(fillStroke.fill.colour);
- pRenderTarget->FillRectangle(&rectFill, pBrush);
+ pRenderTarget->FillRectangle(&rectFill, pBrush.Get());
D2DPenColourAlpha(fillStroke.stroke.colour);
- pRenderTarget->DrawRectangle(&rectOutline, pBrush, fillStroke.stroke.WidthF());
+ pRenderTarget->DrawRectangle(&rectOutline, pBrush.Get(), fillStroke.stroke.WidthF());
}
void SurfaceD2D::RectangleFrame(PRectangle rc, Stroke stroke) {
@@ -1775,7 +1779,7 @@ void SurfaceD2D::RectangleFrame(PRectangle rc, Stroke stroke) {
const XYPOSITION halfStroke = stroke.width / 2.0f;
const D2D1_RECT_F rectangle1 = RectangleFromPRectangle(rc.Inset(halfStroke));
D2DPenColourAlpha(stroke.colour);
- pRenderTarget->DrawRectangle(&rectangle1, pBrush, stroke.WidthF());
+ pRenderTarget->DrawRectangle(&rectangle1, pBrush.Get(), stroke.WidthF());
}
}
@@ -1783,7 +1787,7 @@ void SurfaceD2D::FillRectangle(PRectangle rc, Fill fill) {
if (pRenderTarget) {
D2DPenColourAlpha(fill.colour);
const D2D1_RECT_F rectangle = RectangleFromPRectangle(rc);
- pRenderTarget->FillRectangle(&rectangle, pBrush);
+ pRenderTarget->FillRectangle(&rectangle, pBrush.Get());
}
}
@@ -1797,21 +1801,19 @@ void SurfaceD2D::FillRectangle(PRectangle rc, Surface &surfacePattern) {
if (!psurfOther) {
throw std::runtime_error("SurfaceD2D::FillRectangle: wrong Surface type.");
}
- ID2D1Bitmap *pBitmap = nullptr;
- HRESULT hr = psurfOther->GetBitmap(&pBitmap);
+ ComPtr<ID2D1Bitmap> pBitmap;
+ HRESULT hr = psurfOther->GetBitmap(pBitmap.GetAddressOf());
if (SUCCEEDED(hr) && pBitmap) {
- ID2D1BitmapBrush *pBitmapBrush = nullptr;
+ ComPtr<ID2D1BitmapBrush> pBitmapBrush;
const D2D1_BITMAP_BRUSH_PROPERTIES brushProperties =
D2D1::BitmapBrushProperties(D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP,
D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
// Create the bitmap brush.
- hr = pRenderTarget->CreateBitmapBrush(pBitmap, brushProperties, &pBitmapBrush);
- ReleaseUnknown(pBitmap);
+ hr = pRenderTarget->CreateBitmapBrush(pBitmap.Get(), brushProperties, pBitmapBrush.GetAddressOf());
if (SUCCEEDED(hr) && pBitmapBrush) {
pRenderTarget->FillRectangle(
RectangleFromPRectangle(rc),
- pBitmapBrush);
- ReleaseUnknown(pBitmapBrush);
+ pBitmapBrush.Get());
}
}
}
@@ -1825,19 +1827,19 @@ void SurfaceD2D::RoundedRectangle(PRectangle rc, FillStroke fillStroke) {
RectangleFromPRectangle(rc),
radius, radius };
D2DPenColourAlpha(fillStroke.fill.colour);
- pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
+ pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush.Get());
} else {
const D2D1_ROUNDED_RECT roundedRectFill = {
RectangleFromPRectangle(rc.Inset(1.0)),
radius-1, radius-1 };
D2DPenColourAlpha(fillStroke.fill.colour);
- pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
+ pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush.Get());
const D2D1_ROUNDED_RECT roundedRect = {
RectangleFromPRectangle(rc.Inset(0.5)),
radius, radius };
D2DPenColourAlpha(fillStroke.stroke.colour);
- pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush, fillStroke.stroke.WidthF());
+ pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush.Get(), fillStroke.stroke.WidthF());
}
}
}
@@ -1851,21 +1853,21 @@ void SurfaceD2D::AlphaRectangle(PRectangle rc, XYPOSITION cornerSize, FillStroke
if (cornerSize == 0) {
// When corner size is zero, draw square rectangle to prevent blurry pixels at corners
D2DPenColourAlpha(fillStroke.fill.colour);
- pRenderTarget->FillRectangle(rectFill, pBrush);
+ pRenderTarget->FillRectangle(rectFill, pBrush.Get());
D2DPenColourAlpha(fillStroke.stroke.colour);
- pRenderTarget->DrawRectangle(rectOutline, pBrush, fillStroke.stroke.WidthF());
+ pRenderTarget->DrawRectangle(rectOutline, pBrush.Get(), fillStroke.stroke.WidthF());
} else {
const float cornerSizeF = static_cast<float>(cornerSize);
const D2D1_ROUNDED_RECT roundedRectFill = {
rectFill, cornerSizeF - 1.0f, cornerSizeF - 1.0f };
D2DPenColourAlpha(fillStroke.fill.colour);
- pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
+ pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush.Get());
const D2D1_ROUNDED_RECT roundedRect = {
rectOutline, cornerSizeF, cornerSizeF};
D2DPenColourAlpha(fillStroke.stroke.colour);
- pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush, fillStroke.stroke.WidthF());
+ pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush.Get(), fillStroke.stroke.WidthF());
}
}
}
@@ -1889,22 +1891,20 @@ void SurfaceD2D::GradientRectangle(PRectangle rc, const std::vector<ColourStop>
for (const ColourStop &stop : stops) {
gradientStops.push_back({ static_cast<FLOAT>(stop.position), ColorFromColourAlpha(stop.colour) });
}
- ID2D1GradientStopCollection *pGradientStops = nullptr;
+ ComPtr<ID2D1GradientStopCollection> pGradientStops;
HRESULT hr = pRenderTarget->CreateGradientStopCollection(
- gradientStops.data(), static_cast<UINT32>(gradientStops.size()), &pGradientStops);
+ gradientStops.data(), static_cast<UINT32>(gradientStops.size()), pGradientStops.GetAddressOf());
if (FAILED(hr) || !pGradientStops) {
return;
}
- ID2D1LinearGradientBrush *pBrushLinear = nullptr;
+ ComPtr<ID2D1LinearGradientBrush> pBrushLinear;
hr = pRenderTarget->CreateLinearGradientBrush(
- lgbp, pGradientStops, &pBrushLinear);
+ lgbp, pGradientStops.Get(), pBrushLinear.GetAddressOf());
if (SUCCEEDED(hr) && pBrushLinear) {
const D2D1_RECT_F rectangle = RectangleFromPRectangle(PRectangle(
std::round(rc.left), rc.top, std::round(rc.right), rc.bottom));
- pRenderTarget->FillRectangle(&rectangle, pBrushLinear);
- ReleaseUnknown(pBrushLinear);
+ pRenderTarget->FillRectangle(&rectangle, pBrushLinear.Get());
}
- ReleaseUnknown(pGradientStops);
}
}
@@ -1920,16 +1920,15 @@ void SurfaceD2D::DrawRGBAImage(PRectangle rc, int width, int height, const unsig
std::vector<unsigned char> image(RGBAImage::bytesPerPixel * height * width);
RGBAImage::BGRAFromRGBA(image.data(), pixelsImage, static_cast<ptrdiff_t>(height) * width);
- ID2D1Bitmap *bitmap = nullptr;
+ ComPtr<ID2D1Bitmap> bitmap;
const D2D1_SIZE_U size = D2D1::SizeU(width, height);
const D2D1_BITMAP_PROPERTIES props = {{DXGI_FORMAT_B8G8R8A8_UNORM,
D2D1_ALPHA_MODE_PREMULTIPLIED}, 72.0, 72.0};
const HRESULT hr = pRenderTarget->CreateBitmap(size, image.data(),
- width * 4, &props, &bitmap);
+ width * 4, &props, bitmap.GetAddressOf());
if (SUCCEEDED(hr)) {
const D2D1_RECT_F rcDestination = RectangleFromPRectangle(rc);
- pRenderTarget->DrawBitmap(bitmap, rcDestination);
- ReleaseUnknown(bitmap);
+ pRenderTarget->DrawBitmap(bitmap.Get(), rcDestination);
}
}
}
@@ -1943,13 +1942,13 @@ void SurfaceD2D::Ellipse(PRectangle rc, FillStroke fillStroke) {
const D2D1_ELLIPSE ellipseFill = { centre, radiusFill, radiusFill };
D2DPenColourAlpha(fillStroke.fill.colour);
- pRenderTarget->FillEllipse(ellipseFill, pBrush);
+ pRenderTarget->FillEllipse(ellipseFill, pBrush.Get());
const FLOAT radiusOutline = static_cast<FLOAT>(rc.Width() / 2.0f - fillStroke.stroke.width / 2.0f);
const D2D1_ELLIPSE ellipseOutline = { centre, radiusOutline, radiusOutline };
D2DPenColourAlpha(fillStroke.stroke.colour);
- pRenderTarget->DrawEllipse(ellipseOutline, pBrush, fillStroke.stroke.WidthF());
+ pRenderTarget->DrawEllipse(ellipseOutline, pBrush.Get(), fillStroke.stroke.WidthF());
}
void SurfaceD2D::Stadium(PRectangle rc, FillStroke fillStroke, Ends ends) {
@@ -1968,12 +1967,12 @@ void SurfaceD2D::Stadium(PRectangle rc, FillStroke fillStroke, Ends ends) {
const D2D1_ROUNDED_RECT roundedRectFill = { RectangleInset(rect, fillStroke.stroke.WidthF()),
radiusFill, radiusFill };
D2DPenColourAlpha(fillStroke.fill.colour);
- pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
+ pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush.Get());
const D2D1_ROUNDED_RECT roundedRect = { RectangleInset(rect, halfStroke),
radius, radius };
D2DPenColourAlpha(fillStroke.stroke.colour);
- pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush, fillStroke.stroke.WidthF());
+ pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush.Get(), fillStroke.stroke.WidthF());
} else {
const Ends leftSide = static_cast<Ends>(static_cast<int>(ends) & 0xf);
const Ends rightSide = static_cast<Ends>(static_cast<int>(ends) & 0xf0);
@@ -1983,7 +1982,7 @@ void SurfaceD2D::Stadium(PRectangle rc, FillStroke fillStroke, Ends ends) {
const Geometry pathGeometry = GeometryCreate();
if (!pathGeometry)
return;
- if (const GeometrySink pSink = GeometrySinkCreate(pathGeometry.get())) {
+ if (const GeometrySink pSink = GeometrySinkCreate(pathGeometry.Get())) {
switch (leftSide) {
case Ends::leftFlat:
pSink->BeginFigure(DPointFromPoint(Point(rc.left + halfStroke, rc.top + halfStroke)), D2D1_FIGURE_BEGIN_FILLED);
@@ -2037,23 +2036,22 @@ void SurfaceD2D::Stadium(PRectangle rc, FillStroke fillStroke, Ends ends) {
pSink->Close();
}
D2DPenColourAlpha(fillStroke.fill.colour);
- pRenderTarget->FillGeometry(pathGeometry.get(), pBrush);
+ pRenderTarget->FillGeometry(pathGeometry.Get(), pBrush.Get());
D2DPenColourAlpha(fillStroke.stroke.colour);
- pRenderTarget->DrawGeometry(pathGeometry.get(), pBrush, fillStroke.stroke.WidthF());
+ pRenderTarget->DrawGeometry(pathGeometry.Get(), pBrush.Get(), fillStroke.stroke.WidthF());
}
}
void SurfaceD2D::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
SurfaceD2D &surfOther = dynamic_cast<SurfaceD2D &>(surfaceSource);
- ID2D1Bitmap *pBitmap = nullptr;
- const HRESULT hr = surfOther.GetBitmap(&pBitmap);
+ ComPtr<ID2D1Bitmap> pBitmap;
+ const HRESULT hr = surfOther.GetBitmap(pBitmap.GetAddressOf());
if (SUCCEEDED(hr) && pBitmap) {
const D2D1_RECT_F rcDestination = RectangleFromPRectangle(rc);
const D2D1_RECT_F rcSource = RectangleFromPRectangle(PRectangle(
from.x, from.y, from.x + rc.Width(), from.y + rc.Height()));
- pRenderTarget->DrawBitmap(pBitmap, rcDestination, 1.0f,
+ pRenderTarget->DrawBitmap(pBitmap.Get(), rcDestination, 1.0f,
D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, rcSource);
- ReleaseUnknown(pBitmap);
}
}
@@ -2475,7 +2473,7 @@ void SurfaceD2D::DrawTextCommon(PRectangle rc, const Font *font_, XYPOSITION yba
&pTextLayout);
if (SUCCEEDED(hr)) {
const D2D1_POINT_2F origin = DPointFromPoint(Point(rc.left, ybase - pfm->yAscent));
- pRenderTarget->DrawTextLayout(origin, pTextLayout, pBrush, d2dDrawTextOptions);
+ pRenderTarget->DrawTextLayout(origin, pTextLayout, pBrush.Get(), d2dDrawTextOptions);
ReleaseUnknown(pTextLayout);
}
@@ -3018,7 +3016,7 @@ public:
return false;
}
- const GeometrySink sink = GeometrySinkCreate(geometry.get());
+ const GeometrySink sink = GeometrySinkCreate(geometry.Get());
if (!sink) {
return false;
}
@@ -3034,11 +3032,11 @@ public:
}
if (const BrushSolid pBrushFill = BrushSolidCreate(pTarget.Get(), fillColour)) {
- pTarget->FillGeometry(geometry.get(), pBrushFill.get());
+ pTarget->FillGeometry(geometry.Get(), pBrushFill.Get());
}
if (const BrushSolid pBrushStroke = BrushSolidCreate(pTarget.Get(), strokeColour)) {
- pTarget->DrawGeometry(geometry.get(), pBrushStroke.get(), scale);
+ pTarget->DrawGeometry(geometry.Get(), pBrushStroke.Get(), scale);
}
hr = pTarget->EndDraw();
@@ -3063,7 +3061,7 @@ public:
}
const DWORD penWidth = std::lround(scale);
- HPEN pen;
+ HPEN pen{};
if (penWidth > 1) {
const LOGBRUSH brushParameters { BS_SOLID, strokeColour, 0 };
pen = ::ExtCreatePen(PS_GEOMETRIC | PS_ENDCAP_ROUND | PS_JOIN_MITER,