AUI Framework  master
Cross-platform module-based framework for developing C++20 desktop applications
SoftwareRenderer.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12#pragma once
13
14
15#include <AUI/Render/IRenderer.h>
16#include <AUI/Platform/AWindowBase.h>
17#include <AUI/Platform/SoftwareRenderingContext.h>
18
19class API_AUI_VIEWS SoftwareRenderer: public IRenderer {
20private:
22 bool mDrawingToStencil = false;
23 enum {
24 INCREASE = 1,
25 DECREASE = -1
26 } mDrawingStencilDirection;
27 Blending mBlending = Blending::NORMAL;
28
29public:
41 inline void putPixel(glm::ivec2 position, AColor color, AOptional<Blending> blending = std::nullopt) noexcept {
42 AUI_ASSERTX(mContext != nullptr, "context is null");
43 color = glm::clamp(color, glm::vec4(0), glm::vec4(1));
44 auto actualBlending = blending ? *blending : mBlending;
45 glm::uvec2 uposition(position);
46 if (!glm::all(glm::lessThan(uposition, mContext->bitmapSize()))) return;
47
48 if (mDrawingToStencil) {
49 if (color.a > 0.5f) {
50 mContext->stencil(position) += mDrawingStencilDirection;
51 }
52 } else {
53 auto bufferStencilValue = mContext->stencil(position);
54 if (bufferStencilValue == mStencilDepth)
55 {
56 switch (actualBlending) {
57 case Blending::NORMAL:
58 if (color.a >= 0.9999f) {
59 mContext->putPixel(uposition, glm::u8vec4(glm::vec4(color) * 255.f));
60 } else {
61 // blending
62 auto u8srcColor = mContext->getPixel(uposition);
63 if (u8srcColor.a == 0) {
64 // put the color "as is"
65 mContext->putPixel(uposition, glm::u8vec4(color * 255.f));
66 } else {
67 auto srcColor = glm::vec3(u8srcColor.r, u8srcColor.g, u8srcColor.b);
68 if (u8srcColor.a == 255) {
69 mContext->putPixel(uposition,
70 glm::u8vec4(glm::mix(srcColor, glm::vec3(color) * 255.f, color.a), 255));
71 } else {
72 // blend with the src color; calculate final alpha
73 auto dstColor = glm::vec3(color) * 255.f;
74 auto srcAlpha = float(u8srcColor.a) / 255.f;
75 float finalAlpha = srcAlpha + (1.f - srcAlpha) * color.a;
76 mContext->putPixel(uposition,
77 glm::u8vec4(glm::u8vec3(srcColor * srcAlpha + dstColor * color.a), uint8_t(finalAlpha * 255.f)));
78 }
79 }
80 }
81 break;
82
83 case Blending::ADDITIVE: {
84 auto src = glm::uvec4(glm::vec4(color) * 255.f);
85 src.a = (src.x + src.y + src.z) / 3.f;
86 auto dst = glm::uvec4(mContext->getPixel(uposition));
87 mContext->putPixel(uposition, glm::u8vec4((glm::min)(src + dst, glm::uvec4(255))));
88 break;
89 }
90 case Blending::INVERSE_DST: {
91 auto src = glm::vec3(color);
92 auto dst = glm::vec3(mContext->getPixel(uposition)) / 255.f;
93 mContext->putPixel(uposition, (glm::min)(glm::uvec3((src * (1.f - dst)) * 255.f), glm::uvec3(255)));
94 break;
95 }
96 case Blending::INVERSE_SRC:
97 auto src = glm::vec3(color);
98 auto dstA = glm::vec4(mContext->getPixel(uposition)) / 255.f;
99 auto dst = glm::vec3(dstA);
100 mContext->putPixel(uposition, glm::u8vec4((glm::min)(glm::uvec3(((1.f - src) * dst) * 255.f), glm::uvec3(255)), glm::clamp(color.x + color.y + color.z, dstA.a, 1.f) * 255));
101 break;
102 }
103 }
104 }
105 }
107
108 void rectangle(const ABrush& brush,
109 glm::vec2 position,
110 glm::vec2 size) override;
111
112 void roundedRectangle(const ABrush& brush,
113 glm::vec2 position,
114 glm::vec2 size,
115 float radius) override;
116
117 void rectangleBorder(const ABrush& brush,
118 glm::vec2 position,
119 glm::vec2 size,
120 float lineWidth) override;
121
122 void roundedRectangleBorder(const ABrush& brush,
123 glm::vec2 position,
124 glm::vec2 size,
125 float radius,
126 int borderWidth) override;
127
128 void boxShadow(glm::vec2 position,
129 glm::vec2 size,
130 float blurRadius,
131 const AColor& color) override;
132
133 void boxShadowInner(glm::vec2 position,
134 glm::vec2 size,
135 float blurRadius,
136 float spreadRadius,
137 float borderRadius,
138 const AColor& color,
139 glm::vec2 offset) override;
140
141 void string(glm::vec2 position,
142 const AString& string,
143 const AFontStyle& fs) override;
144
145 _<IPrerenderedString> prerenderString(glm::vec2 position,
146 const AString& text,
147 const AFontStyle& fs) override;
148
149 void setBlending(Blending blending) override;
150
151 void setWindow(AWindowBase* window) override;
152
153 glm::mat4 getProjectionMatrix() const override;
154
155 void pushMaskBefore() override;
156 void pushMaskAfter() override;
157 void popMaskBefore() override;
158 void popMaskAfter() override;
159
160 _unique<IRenderViewToTexture> newRenderViewToTexture() noexcept override;
161
162 void lines(const ABrush& brush, AArrayView<glm::vec2> points, const ABorderStyle& style, AMetric width) override;
163 void points(const ABrush& brush, AArrayView<glm::vec2> points, AMetric size) override;
164
165 void lines(const ABrush& brush, AArrayView<std::pair<glm::vec2, glm::vec2>> points, const ABorderStyle& style, AMetric width) override;
166
167 void squareSector(const ABrush& brush,
168 const glm::vec2& position,
169 const glm::vec2& size,
170 AAngleRadians begin,
171 AAngleRadians end) override;
172protected:
173 _unique<ITexture> createNewTexture() override;
174
175 void drawLine(const ABrush& brush, glm::vec2 p1, glm::vec2 p2, const ABorderStyle& style, AMetric width);
176
177};
178
179
Strong type used to store angle in radians.
Definition: AAngleRadians.h:42
Definition: AArrayView.h:25
Describes border style, like CSS border-style.
Definition: ABorderStyle.h:28
Represents a 4-component floating point color.
Definition: AColor.h:27
Stores dimensions in scalable units (dp, pt, etc...).
Definition: AMetric.h:75
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition: AOptional.h:32
Represents a Unicode character string.
Definition: AString.h:37
Definition: AWindowBase.h:33
Base class for rendering.
Definition: IRenderer.h:149
virtual void popMaskAfter()=0
Switches drawing to the color buffer back from the stencil. Decreases stencil depth.
virtual _< IMultiStringCanvas > newMultiStringCanvas(const AFontStyle &style)=0
Creates new canvas for batching multiple prerender string calls.
virtual void string(glm::vec2 position, const AString &string, const AFontStyle &fs={})=0
Draws string.
virtual void setBlending(Blending blending)=0
Sets blending mode.
virtual void roundedRectangleBorder(const ABrush &brush, glm::vec2 position, glm::vec2 size, float radius, int borderWidth)=0
Draws rounded rectangle's border.
virtual void roundedRectangle(const ABrush &brush, glm::vec2 position, glm::vec2 size, float radius)=0
Draws rounded rect (with antialiasing, if msaa enabled).
virtual void popMaskBefore()=0
Switches drawing to the stencil buffer instead of color buffer.
virtual void setWindow(AWindowBase *window)
Sets the window to render on.
Definition: IRenderer.h:509
virtual void rectangleBorder(const ABrush &brush, glm::vec2 position, glm::vec2 size, float lineWidth=1.f)=0
Draws rectangle's border.
virtual void pushMaskAfter()=0
Switches drawing to the color buffer back from the stencil. Increases stencil depth.
virtual _unique< IRenderViewToTexture > newRenderViewToTexture() noexcept=0
Returns a new instance of IRenderViewToTexture interface associated with this renderer.
virtual void boxShadowInner(glm::vec2 position, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, const AColor &color, glm::vec2 offset)=0
Draws inner (inset) rectangle-shaped shadow.
virtual void boxShadow(glm::vec2 position, glm::vec2 size, float blurRadius, const AColor &color)=0
Draws a rectangle-shaped shadow.
virtual _< IPrerenderedString > prerenderString(glm::vec2 position, const AString &text, const AFontStyle &fs)=0
Analyzes string and creates an instance of IRenderer::IPrerenderedString which helps IRenderer to eff...
virtual void pushMaskBefore()=0
witches drawing to the stencil buffer instead of color buffer.
virtual void rectangle(const ABrush &brush, glm::vec2 position, glm::vec2 size)=0
Draws simple rectangle.
Renderer-friendly image representation.
Definition: ITexture.h:20
Definition: SoftwareRenderer.h:19
void putPixel(glm::ivec2 position, AColor color, AOptional< Blending > blending=std::nullopt) noexcept
Definition: SoftwareRenderer.h:41
Definition: SoftwareRenderingContext.h:17
An std::weak_ptr with AUI extensions.
Definition: SharedPtrTypes.h:177
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition: Assert.h:74
Definition: AFontStyle.h:24
Definition: Size.h:22
Definition: Text.h:21