AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
SoftwareRenderer.h
    1/*
    2 * AUI Framework - Declarative UI toolkit for modern C++20
    3 * Copyright (C) 2020-2025 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:
   21    SoftwareRenderingContext* mContext;
   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:32
Describes border style, like CSS border-style.
Definition ABorderStyle.h:28
Represents a 4-component floating point color (RGBA).
Definition AColor.h:26
Stores dimensions in scalable units (dp, pt, etc...).
Definition AMetric.h:75
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition AOptional.h:33
Represents a Unicode character string.
Definition AString.h:38
Definition AWindowBase.h:33
Renderer-friendly image representation.
Definition ITexture.h:20
Definition SoftwareRenderer.h:19
void setBlending(Blending blending) override
Sets blending mode.
void string(glm::vec2 position, const AString &string, const AFontStyle &fs) override
Draws string.
void squareSector(const ABrush &brush, const glm::vec2 &position, const glm::vec2 &size, AAngleRadians begin, AAngleRadians end) override
Draws sector in rectangle shape. The sector is drawn clockwise from begin to end angles.
void points(const ABrush &brush, AArrayView< glm::vec2 > points, AMetric size) override
Draws points list.
void popMaskBefore() override
Switches drawing to the stencil buffer instead of color buffer.
void boxShadow(glm::vec2 position, glm::vec2 size, float blurRadius, const AColor &color) override
Draws a rectangle-shaped shadow.
void pushMaskAfter() override
Switches drawing to the color buffer back from the stencil. Increases stencil depth.
void setWindow(AWindowBase *window) override
Sets the window to render on.
void rectangle(const ABrush &brush, glm::vec2 position, glm::vec2 size) override
Draws simple rectangle.
void rectangleBorder(const ABrush &brush, glm::vec2 position, glm::vec2 size, float lineWidth) override
Draws rectangle's border.
_< IMultiStringCanvas > newMultiStringCanvas(const AFontStyle &style) override
Creates new canvas for batching multiple prerender string calls.
_< IPrerenderedString > prerenderString(glm::vec2 position, const AString &text, const AFontStyle &fs) override
Analyzes string and creates an instance of IRenderer::IPrerenderedString which helps IRenderer to eff...
void roundedRectangle(const ABrush &brush, glm::vec2 position, glm::vec2 size, float radius) override
Draws rounded rect (with antialiasing, if msaa enabled).
void boxShadowInner(glm::vec2 position, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, const AColor &color, glm::vec2 offset) override
Draws inner (inset) rectangle-shaped shadow.
void popMaskAfter() override
Switches drawing to the color buffer back from the stencil. Decreases stencil depth.
void roundedRectangleBorder(const ABrush &brush, glm::vec2 position, glm::vec2 size, float radius, int borderWidth) override
Draws rounded rectangle's border.
void pushMaskBefore() override
witches drawing to the stencil buffer instead of color buffer.
void lines(const ABrush &brush, AArrayView< glm::vec2 > points, const ABorderStyle &style, AMetric width) override
Draws polyline (non-loop line strip).
void putPixel(glm::ivec2 position, AColor color, AOptional< Blending > blending=std::nullopt) noexcept
Definition SoftwareRenderer.h:41
_unique< IRenderViewToTexture > newRenderViewToTexture() noexcept override
Returns a new instance of IRenderViewToTexture interface associated with this renderer.
Definition SoftwareRenderingContext.h:17
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:179
#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