This repository has been archived by the owner on Jul 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CanvasGeometry.hpp
93 lines (86 loc) · 2.47 KB
/
CanvasGeometry.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#pragma once
#include "framework.h"
#include "winrt.h"
#include "wil.h"
namespace AcrylicEverywhere
{
class CanvasGeometry : public winrt::implements<CanvasGeometry, ABI::Windows::Graphics::IGeometrySource2D, ABI::Windows::Graphics::IGeometrySource2DInterop>
{
winrt::com_ptr<ID2D1Geometry> m_geometry{ nullptr };
public:
IFACEMETHOD(GetGeometry)(
ID2D1Geometry** geometry
) override
{
m_geometry.copy_to(geometry);
return S_OK;
}
IFACEMETHOD(TryGetGeometryUsingFactory)(
ID2D1Factory* factory,
ID2D1Geometry** geometry
) override
{
winrt::com_ptr<ID2D1Factory> geometryFactory{ nullptr };
m_geometry->GetFactory(geometryFactory.put());
if (geometryFactory.get() == factory)
{
m_geometry.copy_to(geometry);
}
return S_OK;
}
static winrt::com_ptr<CanvasGeometry> CreateGeometryFromHRGN(
ID2D1Factory* factory,
HRGN hrgn
) try
{
auto canvasGeometry{ winrt::make_self<CanvasGeometry>() };
auto size{ GetRegionData(hrgn, 0, nullptr) };
THROW_LAST_ERROR_IF(size == 0);
std::unique_ptr<RGNDATA, decltype([](LPRGNDATA ptr) { return free(ptr); })> rgnData{reinterpret_cast<LPRGNDATA>(malloc(size))};
THROW_LAST_ERROR_IF(GetRegionData(hrgn, size, rgnData.get()) == 0);
winrt::com_ptr<ID2D1PathGeometry> geometry{ nullptr };
THROW_IF_FAILED(
factory->CreatePathGeometry(
geometry.put()
)
);
winrt::com_ptr<ID2D1GeometrySink> sink{ nullptr };
THROW_IF_FAILED(geometry->Open(sink.put()));
winrt::com_ptr<ID2D1RectangleGeometry> emptyGeometry{ nullptr };
THROW_IF_FAILED(
factory->CreateRectangleGeometry(
D2D1::RectF(),
emptyGeometry.put()
)
);
for (size_t i = 0; i < rgnData->rdh.nCount; i++)
{
auto rectangle{ &reinterpret_cast<LPRECT>(rgnData->Buffer)[i] };
winrt::com_ptr<ID2D1RectangleGeometry> rectangleGeometry{ nullptr };
THROW_IF_FAILED(
factory->CreateRectangleGeometry(
D2D1::RectF(
static_cast<float>(rectangle->left),
static_cast<float>(rectangle->top),
static_cast<float>(rectangle->right),
static_cast<float>(rectangle->bottom)
),
rectangleGeometry.put()
)
);
THROW_IF_FAILED(
emptyGeometry->CombineWithGeometry(
rectangleGeometry.get(),
D2D1_COMBINE_MODE::D2D1_COMBINE_MODE_UNION,
nullptr,
sink.get()
)
);
}
THROW_IF_FAILED(sink->Close());
canvasGeometry->m_geometry = geometry;
return canvasGeometry;
}
catch(...) { return nullptr; }
};
}