aboutsummaryrefslogtreecommitdiff
path: root/src/graph/graph.hpp
blob: 9ef2e4b8b514e30155a06b7fbd70ac86f5f29cc4 (plain)
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#pragma once

#include "system_headers.hpp"
#include <memory>

#include "base.hpp"
#include "application.hpp"


namespace cru::graph
{
    class GraphManager;

    //Represents a window render target.
    class WindowRenderTarget : public Object
    {
    public:
        WindowRenderTarget(GraphManager* graph_manager, HWND hwnd);
        WindowRenderTarget(const WindowRenderTarget& other) = delete;
        WindowRenderTarget(WindowRenderTarget&& other) = delete;
        WindowRenderTarget& operator=(const WindowRenderTarget& other) = delete;
        WindowRenderTarget& operator=(WindowRenderTarget&& other) = delete;
        ~WindowRenderTarget() override;

    public:
        //Get the graph manager that created the render target.
        GraphManager* GetGraphManager() const
        {
            return graph_manager_;
        }

        //Get the d2d device context.
        inline Microsoft::WRL::ComPtr<ID2D1DeviceContext> GetD2DDeviceContext() const;

        //Get the target bitmap which can be set as the ID2D1DeviceContext's target.
        Microsoft::WRL::ComPtr<ID2D1Bitmap1> GetTargetBitmap() const
        {
            return target_bitmap_;
        }

        //Resize the underlying buffer.
        void ResizeBuffer(int width, int height);

        //Set this render target as the d2d device context's target.
        void SetAsTarget();

        //Present the data of the underlying buffer to the window.
        void Present();

    private:
        void CreateTargetBitmap();

    private:
        GraphManager* graph_manager_;
        Microsoft::WRL::ComPtr<IDXGISwapChain1> dxgi_swap_chain_;
        Microsoft::WRL::ComPtr<ID2D1Bitmap1> target_bitmap_;
    };

    struct Dpi
    {
        float x;
        float y;
    };

    class GraphManager : public Object
    {
    public:
        static GraphManager* GetInstance();

    public:
        GraphManager();
        GraphManager(const GraphManager& other) = delete;
        GraphManager(GraphManager&& other) = delete;
        GraphManager& operator=(const GraphManager& other) = delete;
        GraphManager& operator=(GraphManager&& other) = delete;
        ~GraphManager() override;

    public:
        Microsoft::WRL::ComPtr<ID2D1Factory1> GetD2D1Factory() const
        {
            return d2d1_factory_;
        }

        Microsoft::WRL::ComPtr<ID2D1DeviceContext> GetD2D1DeviceContext() const
        {
            return d2d1_device_context_;
        }

        Microsoft::WRL::ComPtr<ID3D11Device> GetD3D11Device() const
        {
            return d3d11_device_;
        }

        Microsoft::WRL::ComPtr<IDXGIFactory2> GetDxgiFactory() const
        {
            return dxgi_factory_;
        }

        Microsoft::WRL::ComPtr<IDWriteFactory> GetDWriteFactory() const
        {
            return dwrite_factory_;
        }


        //Create a window render target with the HWND.
        std::shared_ptr<WindowRenderTarget> CreateWindowRenderTarget(HWND hwnd);

        //Get the desktop dpi.
        Dpi GetDpi() const;

        //Reload system metrics including desktop dpi.
        void ReloadSystemMetrics();

        Microsoft::WRL::ComPtr<IDWriteFontCollection> GetSystemFontCollection() const
        {
            return dwrite_system_font_collection_.Get();
        }

    private:
        Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
        Microsoft::WRL::ComPtr<ID3D11DeviceContext> d3d11_device_context_;
        Microsoft::WRL::ComPtr<ID2D1Factory1> d2d1_factory_;
        Microsoft::WRL::ComPtr<ID2D1Device> d2d1_device_;
        Microsoft::WRL::ComPtr<ID2D1DeviceContext> d2d1_device_context_;
        Microsoft::WRL::ComPtr<IDXGIFactory2> dxgi_factory_;

        Microsoft::WRL::ComPtr<IDWriteFactory> dwrite_factory_;
        Microsoft::WRL::ComPtr<IDWriteFontCollection> dwrite_system_font_collection_;
    };

    inline int DipToPixelInternal(const float dip, const float dpi)
    {
        return static_cast<int>(dip * dpi / 96.0f);
    }

    inline int DipToPixelX(const float dip_x)
    {
        return DipToPixelInternal(dip_x, Application::GetInstance()->GetGraphManager()->GetDpi().x);
    }

    inline int DipToPixelY(const float dip_y)
    {
        return DipToPixelInternal(dip_y, Application::GetInstance()->GetGraphManager()->GetDpi().y);
    }

    inline float DipToPixelInternal(const int pixel, const float dpi)
    {
        return static_cast<float>(pixel) * 96.0f / dpi;
    }

    inline float PixelToDipX(const int pixel_x)
    {
        return DipToPixelInternal(pixel_x, Application::GetInstance()->GetGraphManager()->GetDpi().x);
    }

    inline float PixelToDipY(const int pixel_y)
    {
        return DipToPixelInternal(pixel_y, Application::GetInstance()->GetGraphManager()->GetDpi().y);
    }

    Microsoft::WRL::ComPtr<ID2D1DeviceContext> WindowRenderTarget::GetD2DDeviceContext() const
    {
        return graph_manager_->GetD2D1DeviceContext();
    }

    Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> CreateSolidBrush(const D2D1_COLOR_F& color);
    Microsoft::WRL::ComPtr<IDWriteTextFormat> CreateDefaultTextFormat();

    inline void WithTransform(ID2D1DeviceContext* device_context, const D2D1_MATRIX_3X2_F matrix, const std::function<void(ID2D1DeviceContext*)>& action)
    {
        D2D1_MATRIX_3X2_F old_transform;
        device_context->GetTransform(&old_transform);
        device_context->SetTransform(old_transform * matrix);
        action(device_context);
        device_context->SetTransform(old_transform);
    }
}