M module-gui/gui/core/Context.hpp => module-gui/gui/core/Context.hpp +7 -1
@@ 13,7 13,7 @@
#include <cstdint>
#include <iostream>
-#include "Common.hpp"
+#include "module-gui/gui/Common.hpp"
namespace gui
{
@@ 81,6 81,12 @@ namespace gui
return (ptr >= data) && (ptr < data + w * h);
}
+ inline bool addressInData(const Point point) const noexcept
+ {
+ return (point.x >= 0 && static_cast<uint32_t>(point.x) <= w) &&
+ (point.y >= 0 && static_cast<uint32_t>(point.y) <= h);
+ }
+
friend std::ostream &operator<<(std::ostream &out, const Context &c);
};
M module-gui/gui/core/DrawCommand.cpp => module-gui/gui/core/DrawCommand.cpp +284 -9
@@ 1,14 1,289 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-/*
- * DrawCommand.cpp
- *
- * Created on: 25 kwi 2019
- * Author: robert
- */
-
#include "DrawCommand.hpp"
+#include "Common.hpp"
+
+// gui components
+#include "Color.hpp"
+#include "Context.hpp"
+#include "ImageManager.hpp"
+// renderers
+#include "renderers/LineRenderer.hpp"
+#include "renderers/ArcRenderer.hpp"
+#include "renderers/CircleRenderer.hpp"
+#include "renderers/RectangleRenderer.hpp"
+#include <renderers/PixelRenderer.hpp>
+// text rendering
+#include "FontManager.hpp"
+#include "RawFont.hpp"
+// utils
+#include "log/log.hpp"
+// module-utils
+#include <cmath>
+#include <cassert>
+
+#if DEBUG_FONT == 1
+#define log_warn_glyph(...) LOG_WARN(__VA_ARGS__)
+#else
+#define log_warn_glyph(...)
+#endif
namespace gui
-{} /* namespace gui */
+{
+ void Clear::draw(Context *ctx) const
+ {
+ ctx->fill(ColorFullWhite.intensity);
+ }
+
+ void DrawLine::draw(Context *ctx) const
+ {
+ renderer::LineRenderer::draw(ctx, start, end, color);
+ }
+
+ void DrawRectangle::draw(Context *ctx) const
+ {
+ using renderer::RectangleRenderer;
+
+ // First, check if there is anything to draw
+ if (width == 0 || height == 0) {
+ return;
+ }
+ if (fillColor.alpha == Color::FullTransparent && borderColor.alpha == Color::FullTransparent) {
+ return;
+ }
+ if (!filled && borderColor.alpha == Color::FullTransparent) {
+ return;
+ }
+
+ Context *drawingContext = ctx;
+ Point position;
+
+ if (yaps & (RectangleYap::BottomLeft | RectangleYap::TopLeft)) {
+ position.x += yapSize;
+ }
+
+ Length adjustedWidth = areaW;
+ Length adjustedHeight = areaH;
+ if (yaps != RectangleYap::None) {
+ adjustedWidth -= yapSize;
+ }
+
+ if (areaW == width && areaH == height) {
+ position.x += origin.x;
+ position.y += origin.y;
+ }
+ else {
+ const auto xCtx = areaX < 0 ? origin.x + areaX : origin.x;
+ const auto yCtx = areaY < 0 ? origin.y + areaY : origin.y;
+ drawingContext = ctx->get(xCtx, yCtx, areaW, areaH);
+ }
+
+ if (radius == 0) {
+ RectangleRenderer::drawFlat(
+ drawingContext, position, adjustedWidth, adjustedHeight, RectangleRenderer::DrawableStyle::from(*this));
+ }
+ else {
+ RectangleRenderer::draw(
+ drawingContext, position, adjustedWidth, adjustedHeight, RectangleRenderer::DrawableStyle::from(*this));
+ }
+
+ if (drawingContext != ctx) {
+ ctx->insertArea(origin.x, origin.y, areaX, areaY, width, height, drawingContext);
+ delete drawingContext;
+ }
+ }
+
+ void DrawArc::draw(Context *ctx) const
+ {
+ renderer::ArcRenderer::draw(
+ ctx, center, radius, start, sweep, renderer::ArcRenderer::DrawableStyle::from(*this));
+ }
+
+ void DrawCircle::draw(Context *ctx) const
+ {
+ renderer::CircleRenderer::draw(ctx, center, radius, renderer::CircleRenderer::DrawableStyle::from(*this));
+ }
+
+ void DrawText::drawChar(Context *ctx, const Point glyphOrigin, FontGlyph *glyph) const
+ {
+ auto *glyphPtr = glyph->data - glyphOrigin.x;
+ assert(glyph->data);
+
+ Point position = glyphOrigin;
+ const Position glyphMaxY = glyphOrigin.y - glyph->yoffset + glyph->height;
+ const Position glyphMaxX = glyphOrigin.x + glyph->width;
+
+ for (position.y = glyphOrigin.y - glyph->yoffset; position.y < glyphMaxY; ++position.y) {
+ for (position.x = glyphOrigin.x; position.x < glyphMaxX; ++position.x) {
+ if (!ctx->addressInData(position)) {
+ log_warn_glyph(
+ "drawing out of: {x=%d,y=%d} vs {w=%d,h=%d}", position.x, position.y, ctx->getW(), ctx->getH());
+ return;
+ }
+
+ if (*(glyphPtr + position.x) == ColorFullBlack.intensity) {
+ renderer::PixelRenderer::draw(ctx, position, color);
+ }
+ }
+ glyphPtr += glyph->width;
+ }
+ }
+
+ void DrawText::draw(Context *ctx) const
+ {
+ // check if there are any characters to draw in the string provided with message.
+ if (str.length() == 0) {
+ return;
+ }
+
+ // get copy of original context using x,y of draw coordinates and original size of the widget
+ Context *drawCtx;
+ bool copyContext = false;
+ Point widgetOrigin = {0, 0};
+
+ // check if there is a need of making copy of context to use it as background
+ if ((areaW == width) && (areaH == height)) {
+ drawCtx = ctx;
+ widgetOrigin = origin;
+ }
+ else {
+ copyContext = true;
+ drawCtx = ctx->get(origin.x, origin.y, areaW, areaH);
+ }
+
+ // retrieve font used to draw text
+ RawFont *font = FontManager::getInstance().getFont(fontID);
+
+ // draw every sign
+ uint32_t idLast = 0, idCurrent = 0;
+ Point position = textOrigin;
+
+ for (uint32_t i = 0; i < str.length(); ++i) {
+ idCurrent = str[i]; // id stands for glued together utf-16 with no order bytes (0xFF 0xFE)
+ FontGlyph *glyph = font->getGlyph(idCurrent);
+
+ // do not start drawing outside of draw context.
+ if ((widgetOrigin.x + position.x + glyph->xoffset >= drawCtx->getW()) ||
+ (widgetOrigin.x + position.x + glyph->xoffset < 0)) {
+ LOG_FATAL("Drawing outside context's X boundary for glyph: %" PRIu32, glyph->id);
+ return;
+ }
+ if ((widgetOrigin.y + position.y >= drawCtx->getH()) || (widgetOrigin.y + position.y < 0)) {
+ LOG_FATAL("Drawing outside context's Y boundary for glyph: %" PRIu32, glyph->id);
+ return;
+ }
+
+ int32_t kernValue = 0;
+ if (i > 0) {
+ kernValue = font->getKerning(idLast, idCurrent);
+ }
+
+ drawChar(drawCtx,
+ {widgetOrigin.x + position.x + glyph->xoffset + kernValue, widgetOrigin.y + position.y},
+ glyph);
+ position.x += glyph->xadvance + kernValue;
+
+ idLast = idCurrent;
+ }
+
+ // if drawing was performed in temporary context
+ // reinsert drawCtx into bast context
+ if (copyContext) {
+ ctx->insert(origin.x, origin.y, drawCtx);
+ delete drawCtx;
+ }
+ }
+
+ inline void DrawImage::checkImageSize(Context *ctx, ImageMap *image) const
+ {
+ if (image->getHeight() > ctx->getH() || image->getWidth() > ctx->getW()) {
+ LOG_WARN("image %s {w: %d,h %d} > context {w %d,h %d}",
+ image->getName().c_str(),
+ image->getWidth(),
+ ctx->getW(),
+ image->getHeight(),
+ ctx->getH());
+ }
+ }
+
+ void DrawImage::drawPixMap(Context *ctx, PixMap *pixMap) const
+ {
+ uint32_t offsetImage = 0;
+ uint32_t offsetContext = 0;
+ uint8_t *pixData = pixMap->getData();
+ const auto ctxData = ctx->getData();
+ checkImageSize(ctx, pixMap);
+
+ for (uint32_t row = 0; row < std::min(ctx->getH(), pixMap->getHeight()); row++) {
+ std::memcpy(ctxData + offsetContext, pixData + offsetImage, std::min(ctx->getW(), pixMap->getWidth()));
+ offsetImage += pixMap->getWidth();
+ offsetContext += ctx->getW();
+ }
+ }
+
+ void DrawImage::drawVecMap(Context *ctx, VecMap *vecMap) const
+ {
+ uint32_t offsetContext = 0;
+ uint32_t offsetRowContext = 0;
+ uint32_t imageOffset = 0;
+ uint8_t alphaColor = vecMap->getAlphaColor();
+
+ for (uint32_t row = 0; row < std::min(vecMap->getHeight(), ctx->getH()); row++) {
+ checkImageSize(ctx, vecMap);
+ uint16_t vecCount = *(vecMap->getData() + imageOffset);
+ imageOffset += sizeof(uint16_t);
+
+ const auto ctxData = ctx->getData();
+ offsetRowContext = offsetContext;
+
+ for (uint32_t vec = 0; vec < vecCount; ++vec) {
+
+ uint16_t vecOffset = *(vecMap->getData() + imageOffset);
+ imageOffset += sizeof(uint16_t);
+ uint16_t vecLength = *(vecMap->getData() + imageOffset);
+ imageOffset += sizeof(uint8_t);
+ uint8_t vecColor = *(vecMap->getData() + imageOffset);
+ imageOffset += sizeof(uint8_t);
+
+ offsetRowContext += vecOffset;
+ if (vecColor != alphaColor) {
+ std::memset(ctxData + offsetRowContext, vecColor, std::min(ctx->getW(), vecLength));
+ }
+ offsetRowContext += vecLength;
+ }
+ offsetContext += ctx->getW();
+ }
+ }
+
+ void DrawImage::draw(Context *ctx) const
+ {
+ // retrieve pixmap from the pixmap manager
+ ImageMap *imageMap = ImageManager::getInstance().getImageMap(imageID);
+
+ // if image is not found return;
+ if (imageMap == nullptr) {
+ return;
+ }
+
+ // get copy of original context using x,y of draw coordinates and original size of the widget
+ Context *drawCtx = ctx->get(origin.x, origin.y, areaW, areaH);
+
+ if (imageMap->getType() == gui::ImageMap::Type::PIXMAP) {
+ auto pixMap = dynamic_cast<PixMap *>(imageMap);
+ assert(pixMap);
+ drawPixMap(drawCtx, pixMap);
+ }
+ else if (imageMap->getType() == gui::ImageMap::Type::VECMAP) {
+ auto vecMap = dynamic_cast<VecMap *>(imageMap);
+ assert(vecMap);
+ drawVecMap(drawCtx, vecMap);
+ }
+
+ // reinsert drawCtx into bast context
+ ctx->insert(origin.x, origin.y, drawCtx);
+
+ // remove draw context
+ delete drawCtx;
+ }
+} /* namespace gui */
M module-gui/gui/core/DrawCommand.hpp => module-gui/gui/core/DrawCommand.hpp +101 -149
@@ 10,218 10,170 @@
#include <gui/Common.hpp>
#include "Color.hpp"
+#include "Context.hpp"
+#include <FontGlyph.hpp>
+
+// image
+#include "PixMap.hpp"
+#include "VecMap.hpp"
namespace gui
{
-
- enum class DrawCommandID
- {
- GUI_DRAW_UNDEFINED = 0,
- GUI_DRAW_CLEAR = 1,
- GUI_DRAW_LINE,
- GUI_DRAW_TRIANGLE,
- GUI_DRAW_RECT,
- GUI_DRAW_TEXT,
- GUI_DRAW_ARC,
- GUI_DRAW_PIE,
- GUI_DRAW_CIRCLE,
- GUI_DRAW_IMAGE,
- GUI_DRAW_COMMANDS, // blob of many
- GUI_RENDER_QUICK,
- GUI_RENDER_DEEP,
- GUI_RENDER_REFRESH // sent to applications so they can repaint current window
- };
-
+ /**
+ * @brief Draw command interface.
+ */
class DrawCommand
{
public:
- DrawCommandID id;
+ int16_t areaX{0};
+ int16_t areaY{0};
+ Length areaW{0};
+ Length areaH{0};
- int16_t areaX;
- int16_t areaY;
- int16_t areaW;
- int16_t areaH;
+ virtual ~DrawCommand() = default;
- DrawCommand() : id{DrawCommandID::GUI_DRAW_UNDEFINED}, areaX{0}, areaY{0}, areaW{0}, areaH{0} {};
- virtual ~DrawCommand(){};
+ virtual void draw(Context *ctx) const = 0;
};
- class CommandRender : public DrawCommand
+ class Clear : public DrawCommand
{
- public:
- std::string applicationName;
- CommandRender()
- {
- id = DrawCommandID::GUI_RENDER_DEEP;
- };
- };
-
- class CommandLine : public DrawCommand
- {
- public:
- int16_t x1;
- int16_t y1;
- int16_t x2;
- int16_t y2;
- Color color;
- uint8_t penWidth;
-
- CommandLine() : x1{0}, y1{0}, x2{0}, y2{0}, color(ColorFullBlack), penWidth{1}
- {
- id = DrawCommandID::GUI_DRAW_LINE;
- }
+ void draw(Context *ctx) const override;
};
/**
- * @brief Draw command for triangle.
+ * @brief Draw command for line.
*/
- class CommandTriangle : DrawCommand
+ class DrawLine : public DrawCommand
{
public:
- int16_t x1;
- int16_t y1;
- int16_t x2;
- int16_t y2;
- int16_t x3;
- int16_t y3;
- Color fillColor;
- gui::Color borderColor;
- uint8_t penWidth;
-
- CommandTriangle()
- : x1{0}, y1{0}, x2{0}, y2{0}, x3{0}, y3{0}, fillColor(ColorFullBlack),
- borderColor(ColorFullBlack), penWidth{1}
- {
- id = DrawCommandID::GUI_DRAW_TRIANGLE;
- }
+ Point start{0, 0};
+ Point end{0, 0};
+ Color color{ColorFullBlack};
+ uint8_t penWidth{1};
+
+ public:
+ void draw(Context *ctx) const override;
};
/**
* @brief Draw command for rectangle.
*/
- class CommandRectangle : public DrawCommand
+ class DrawRectangle : public DrawCommand
{
public:
- int16_t x;
- int16_t y;
- uint16_t w;
- uint16_t h;
- uint16_t radius;
+ Point origin{0, 0};
+ Length width{0};
+ Length height{0};
+ Length radius{0};
+
// flags that defines whether paint given border
- RectangleEdge edges;
+ RectangleEdge edges{RectangleEdge::All};
// flags that defines which edge should be flat. This will disable roundness on both sides of the edge.
- RectangleFlatEdge flatEdges;
+ RectangleFlatEdge flatEdges{RectangleFlatEdge::None};
// flags that defines whether paint given corner (only for rounded corners)
- RectangleRoundedCorner corners;
+ RectangleRoundedCorner corners{RectangleRoundedCorner::All};
// flags indicating yaps for speech bubbles, it takes precendece over other properties
- RectangleYap yaps;
+ RectangleYap yaps{RectangleYap::None};
// defines which of the edges and corners are painted
- unsigned short yapSize = 0;
- bool filled;
- uint8_t penWidth;
- Color fillColor;
- Color borderColor;
- CommandRectangle()
- : x{0}, y{0}, w{0}, h{0}, radius{0}, edges{RectangleEdge::All}, flatEdges{RectangleFlatEdge::None},
- corners{RectangleRoundedCorner::All}, yaps{RectangleYap::None}, yapSize{0}, filled{false}, penWidth{1},
- fillColor(ColorFullBlack), borderColor(ColorFullBlack)
- {
- id = DrawCommandID::GUI_DRAW_RECT;
- }
+ unsigned short yapSize{0};
+
+ bool filled{false};
+ uint8_t penWidth{1};
+ Color fillColor{ColorFullBlack};
+ Color borderColor{ColorFullBlack};
+
+ public:
+ void draw(Context *ctx) const override;
};
- class CommandArc : public DrawCommand
+ /**
+ * @brief Draw command for arc.
+ */
+ class DrawArc : public DrawCommand
{
public:
- CommandArc(Point _center,
- Length _radius,
- trigonometry::Degrees _start,
- trigonometry::Degrees _sweep,
- uint8_t _width,
- Color _color)
- : center{_center}, radius{_radius}, start{_start}, sweep{_sweep}, width{_width}, borderColor{_color}
- {
- id = DrawCommandID::GUI_DRAW_ARC;
- }
-
- const Point center;
- const Length radius;
const trigonometry::Degrees start;
const trigonometry::Degrees sweep;
- const uint8_t width;
+ const Length width;
const Color borderColor;
+ const Point center;
+ const Length radius;
+
+ DrawArc(Point _center,
+ Length _radius,
+ trigonometry::Degrees _start,
+ trigonometry::Degrees _sweep,
+ Length _width,
+ Color _color)
+ : start{_start}, sweep{_sweep}, width{_width}, borderColor{_color}, center{_center}, radius{_radius}
+ {}
+
+ void draw(Context *ctx) const override;
};
/**
* @brief Draw command for circle.
*/
- class CommandCircle : public CommandArc
+ class DrawCircle : public DrawArc
{
public:
- CommandCircle(Point _center,
- Length _radius,
- uint8_t _borderWidth,
- Color _borderColor,
- bool _filled = false,
- Color _fillColor = {})
- : CommandArc{_center, _radius, 0, trigonometry::FullAngle, _borderWidth, _borderColor}, filled{_filled},
- fillColor{_fillColor}
- {
- id = DrawCommandID::GUI_DRAW_CIRCLE;
- }
-
const bool filled;
const Color fillColor;
+
+ DrawCircle(Point _center,
+ Length _radius,
+ Length _borderWidth,
+ Color _borderColor,
+ bool _filled = false,
+ Color _fillColor = {})
+ : DrawArc{_center, _radius, 0, trigonometry::FullAngle, _borderWidth, _borderColor}, filled{_filled},
+ fillColor{_fillColor}
+ {}
+
+ void draw(Context *ctx) const override;
};
/**
* @brief Draw command for text line.
*/
- class CommandText : public DrawCommand
+ class DrawText : public DrawCommand
{
public:
- // area where label wil lbe drawn
- int16_t x;
- int16_t y;
- int16_t w;
- int16_t h;
+ // area where label wil be drawn
+ Point origin{0, 0};
+ Length width{0};
+ Length height{0};
// area occupied by text inside the label
- int16_t tx;
- int16_t ty;
- int16_t tw;
- int16_t th;
- uint16_t charsWidth; // number of visible pixels calculated
- UTF8 str;
- uint8_t fontID;
-
- Color color;
-
- CommandText()
- : x{0}, y{0}, w{0}, h{0}, tx{0}, ty{0}, tw{0}, th{0}, charsWidth{0}, str{""}, fontID{0},
- color(ColorFullBlack)
- {
- id = DrawCommandID::GUI_DRAW_TEXT;
- }
+ Point textOrigin{0, 0};
+ Length textHeight{0};
+
+ UTF8 str{};
+ uint8_t fontID{0};
+ Color color{ColorFullBlack};
+
+ void draw(Context *ctx) const override;
+
+ private:
+ void drawChar(Context *ctx, const Point glyphOrigin, FontGlyph *glyph) const;
};
/**
* @brief Draw command for image.
*/
- class CommandImage : public DrawCommand
+ class DrawImage : public DrawCommand
{
public:
- int16_t x;
- int16_t y;
- uint16_t w;
- uint16_t h;
+ Point origin{0, 0};
// ID of the image
- uint16_t imageID;
+ uint16_t imageID{0};
+
+ void draw(Context *ctx) const override;
- CommandImage() : x{0}, y{0}, w{0}, h{0}, imageID{0}
- {
- id = DrawCommandID::GUI_DRAW_IMAGE;
- }
+ private:
+ void drawPixMap(Context *ctx, PixMap *pixMap) const;
+ void drawVecMap(Context *ctx, VecMap *vecMap) const;
+ inline void checkImageSize(Context *ctx, ImageMap *image) const;
};
} /* namespace gui */
M module-gui/gui/core/RawFont.cpp => module-gui/gui/core/RawFont.cpp +6 -7
@@ 4,7 4,7 @@
#include "RawFont.hpp"
#include "Common.hpp" // for Status, Status::GUI_SUCCESS, Status::GU...
#include "Context.hpp" // for Context
-#include "DrawCommand.hpp" // for CommandRectangle, DrawCommand (ptr only)
+#include "DrawCommand.hpp" // for DrawRectangle, DrawCommand (ptr only)
#include "FontKerning.hpp" // for FontKerning
#include "Renderer.hpp" // for Renderer
#include "TextConstants.hpp" // for newline
@@ 294,18 294,17 @@ namespace gui
unsupported->xadvance =
unsupported->width + (2 * unsupported->xoffset); // use xoffset as margins on the left/right of the glyph
// populate with a bitmap (glyph)
- auto commandRect = std::make_unique<CommandRectangle>();
- commandRect->x = 0;
- commandRect->y = 0;
- commandRect->w = unsupported->width;
- commandRect->h = unsupported->height;
+ auto commandRect = std::make_unique<DrawRectangle>();
+ commandRect->origin = {0, 0};
+ commandRect->width = unsupported->width;
+ commandRect->height = unsupported->height;
commandRect->areaX = 0;
commandRect->areaY = 0;
commandRect->areaW = unsupported->width;
commandRect->areaH = unsupported->height;
commandRect->penWidth = unsupported->xoffset;
- auto renderCtx = std::make_unique<Context>(unsupported->width, unsupported->height);
+ auto renderCtx = std::make_unique<Context>(unsupported->width, unsupported->height);
std::list<std::unique_ptr<gui::DrawCommand>> commands;
commands.emplace_back(std::move(commandRect));
Renderer().render(renderCtx.get(), commands);
M module-gui/gui/core/Renderer.cpp => module-gui/gui/core/Renderer.cpp +4 -307
@@ 1,327 1,24 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-extern "C"
-{
-#include "FreeRTOS.h"
-#include "task.h"
-}
-
// for memset
-#include <string.h>
-#include "Color.hpp"
#include "Renderer.hpp"
#include "Context.hpp"
-#include "ImageManager.hpp"
-#include "../Common.hpp"
-// renderers
-#include "renderers/LineRenderer.hpp"
-#include "renderers/ArcRenderer.hpp"
-#include "renderers/CircleRenderer.hpp"
-#include "renderers/RectangleRenderer.hpp"
-// utils
-#include "log/log.hpp"
-
-#include "PixMap.hpp"
-#include "VecMap.hpp"
-// module-utils
-#include "utf8/UTF8.hpp"
-#include <cmath>
-#include <cassert>
-#include <FontManager.hpp>
-#include <FontGlyph.hpp>
-#include <RawFont.hpp>
-#include "Style.hpp"
-#include "Common.hpp"
-
-#if DEBUG_FONT == 1
-#define log_warn_glyph(...) LOG_WARN(__VA_ARGS__)
-#else
-#define log_warn_glyph(...)
-#endif
namespace gui
{
- void Renderer::drawLine(Context *ctx, CommandLine *cmd)
- {
- using renderer::LineRenderer;
- const Point p1{cmd->x1, cmd->y1};
- const Point p2{cmd->x2, cmd->y2};
- const auto color = cmd->color;
- LineRenderer::draw(ctx, p1, p2, color);
- }
-
- void Renderer::drawRectangle(Context *ctx, CommandRectangle *cmd)
- {
- using renderer::RectangleRenderer;
-
- // First, check if there is anything to draw
- if (cmd->w == 0 || cmd->h == 0) {
- return;
- }
- if (cmd->fillColor.alpha == Color::FullTransparent && cmd->borderColor.alpha == Color::FullTransparent) {
- return;
- }
- if (!cmd->filled && cmd->borderColor.alpha == Color::FullTransparent) {
- return;
- }
-
- Context *drawingContext = ctx;
- Point position;
- if (cmd->yaps & (RectangleYap::BottomLeft | RectangleYap::TopLeft)) {
- position.x += cmd->yapSize;
- }
- Length width = cmd->areaW;
- Length height = cmd->areaH;
- if (cmd->yaps != RectangleYap::None) {
- width -= cmd->yapSize;
- }
-
- if (cmd->areaW == cmd->w && cmd->areaH == cmd->h) {
- position.x += cmd->x;
- position.y += cmd->y;
- }
- else {
- const auto x = cmd->areaX < 0 ? cmd->x + cmd->areaX : cmd->x;
- const auto y = cmd->areaY < 0 ? cmd->y + cmd->areaY : cmd->y;
- drawingContext = ctx->get(x, y, cmd->areaW, cmd->areaH);
- }
-
- Length radius = cmd->radius;
- if (radius == 0) {
- RectangleRenderer::drawFlat(
- drawingContext, position, width, height, RectangleRenderer::DrawableStyle::from(*cmd));
- }
- else {
- RectangleRenderer::draw(
- drawingContext, position, width, height, RectangleRenderer::DrawableStyle::from(*cmd));
- }
-
- if (drawingContext != ctx) {
- ctx->insertArea(cmd->x, cmd->y, cmd->areaX, cmd->areaY, cmd->w, cmd->h, drawingContext);
- delete drawingContext;
- }
- }
-
- void Renderer::drawArc(Context *ctx, CommandArc *cmd)
- {
- using renderer::ArcRenderer;
- const auto center{cmd->center};
- const auto radius{cmd->radius};
- const auto startAngle{cmd->start};
- const auto sweepAngle{cmd->sweep};
- const auto style = ArcRenderer::DrawableStyle::from(*cmd);
- ArcRenderer::draw(ctx, center, radius, startAngle, sweepAngle, style);
- }
-
- void Renderer::drawCircle(Context *ctx, CommandCircle *cmd)
- {
- using renderer::CircleRenderer;
- const auto center{cmd->center};
- const auto radius{cmd->radius};
- const auto style = CircleRenderer::DrawableStyle::from(*cmd);
- CircleRenderer::draw(ctx, center, radius, style);
- }
-
- void Renderer::drawChar(Context *context, const int16_t x, const int16_t y, FontGlyph *glyph, const Color color)
- {
- auto line_y_offset = (y - glyph->yoffset) * context->getW();
- auto *drawPtr = context->getData() + x + line_y_offset;
- auto *glyphPtr = glyph->data;
- assert(glyph->data);
-
- for (uint16_t yy = 0; yy < glyph->height; ++yy) {
- for (uint16_t xx = 0; xx < glyph->width; ++xx) {
- if (!context->addressInData(drawPtr + xx)) {
- log_warn_glyph("drawing out of: %d vs %d", xx, context->getW() * context->getH());
- return;
- }
- if (*(glyphPtr + xx) == 0) {
- *(drawPtr + xx) = 0x0F & color.intensity;
- }
- }
- drawPtr += context->getW();
- glyphPtr += glyph->width;
- }
- }
-
- void Renderer::drawText(Context *ctx, CommandText *cmd)
- {
-
- // check if there are any characters to draw in the string provided with message.
- if (cmd->str.length() == 0) {
- return;
- }
-
- // get copy of original context using x,y of draw coordinates and original size of the widget
- Context *drawCtx;
- bool copyContext = false;
- int16_t wgtX = 0, wgtY = 0;
- // check if there is a need or making copy of context to use it as background
- if ((cmd->areaW == cmd->w) && (cmd->areaH == cmd->h)) {
- drawCtx = ctx;
- wgtX = cmd->x;
- wgtY = cmd->y;
- }
- else {
- copyContext = true;
- drawCtx = ctx->get(cmd->x, cmd->y, cmd->areaW, cmd->areaH);
- }
-
- // retrieve font used to draw text
- FontManager &fontManager = FontManager::getInstance();
- RawFont *font = fontManager.getFont(cmd->fontID);
-
- int16_t posX = cmd->tx;
- int16_t posY = cmd->ty;
-
- // draw every sign
- uint32_t idLast = 0, idCurrent = 0;
- for (uint32_t i = 0; i < cmd->str.length(); ++i) {
- idCurrent = cmd->str[i]; // id stands for glued together utf-16 with no order bytes (0xFF 0xFE)
- FontGlyph *glyph = font->getGlyph(idCurrent);
-
- // do not start drawing outside of draw context.
- if ((wgtX + posX + glyph->xoffset >= drawCtx->getW()) || (wgtX + posX + glyph->xoffset < 0)) {
- LOG_FATAL("Drawing outside context's X boundary for glyph: %" PRIu32, glyph->id);
- return;
- }
- if ((wgtY + posY >= drawCtx->getH()) || (wgtY + posY < 0)) {
- LOG_FATAL("Drawing outside context's Y boundary for glyph: %" PRIu32, glyph->id);
- return;
- }
-
- int32_t kernValue = 0;
- if (i > 0) {
- kernValue = font->getKerning(idLast, idCurrent);
- }
- drawChar(drawCtx, wgtX + posX + glyph->xoffset + kernValue, wgtY + posY, glyph, cmd->color);
- posX += glyph->xadvance + kernValue;
-
- idLast = idCurrent;
- }
-
- // if drawing was performed in temporary context
- // reinsert drawCtx into bast context
- if (copyContext) {
- ctx->insert(cmd->x, cmd->y, drawCtx);
- delete drawCtx;
- }
- }
-
- void Renderer::drawImage(Context *ctx, CommandImage *cmd)
- {
-
- // retrive pixmap from the pixmap manager
- ImageMap *imageMap = ImageManager::getInstance().getImageMap(cmd->imageID);
-
- // if image is not found return;
- if (imageMap == nullptr)
- return;
-
- // get copy of original context using x,y of draw coordinates and original size of the widget
- Context *drawCtx = ctx->get(cmd->x, cmd->y, cmd->areaW, cmd->areaH);
- uint8_t *ctxData = drawCtx->getData();
-
- auto check_wh = [&](const std::string &name, auto w, auto h) {
- if (h > ctx->getH() || w > ctx->getW()) {
- LOG_WARN("image %s {w: %d,h %d} > context {w %d,h %d}",
- name.c_str(),
- w,
- drawCtx->getW(),
- h,
- drawCtx->getH());
- }
- };
-
- if (imageMap->getType() == gui::ImageMap::Type::PIXMAP) {
- auto pixMap = dynamic_cast<PixMap *>(imageMap);
- assert(pixMap);
- uint32_t offsetImage = 0;
- uint32_t offsetContext = 0;
- uint8_t *pixData = pixMap->getData();
- check_wh(pixMap->getName(), pixMap->getWidth(), pixMap->getHeight());
-
- for (uint32_t row = 0; row < std::min(drawCtx->getH(), pixMap->getHeight()); row++) {
- memcpy(ctxData + offsetContext, pixData + offsetImage, std::min(drawCtx->getW(), pixMap->getWidth()));
- offsetImage += pixMap->getWidth();
- offsetContext += drawCtx->getW();
- }
- }
- else if (imageMap->getType() == gui::ImageMap::Type::VECMAP) {
- auto vecMap = dynamic_cast<VecMap *>(imageMap);
- assert(vecMap);
- uint32_t offsetContext = 0;
- uint32_t offsetRowContext = 0;
- uint32_t imageOffset = 0;
- uint8_t alphaColor = vecMap->getAlphaColor();
- for (uint32_t row = 0; row < std::min(vecMap->getHeight(), drawCtx->getH()); row++) {
- check_wh(vecMap->getName(), imageMap->getWidth(), imageMap->getHeight());
- uint16_t vecCount = *(vecMap->getData() + imageOffset);
- imageOffset += sizeof(uint16_t);
-
- offsetRowContext = offsetContext;
-
- for (uint32_t vec = 0; vec < vecCount; ++vec) {
-
- uint16_t vecOffset = *(vecMap->getData() + imageOffset);
- imageOffset += sizeof(uint16_t);
- uint16_t vecLength = *(vecMap->getData() + imageOffset);
- imageOffset += sizeof(uint8_t);
- uint8_t vecColor = *(vecMap->getData() + imageOffset);
- imageOffset += sizeof(uint8_t);
-
- offsetRowContext += vecOffset;
- if (vecColor != alphaColor) {
- memset(ctxData + offsetRowContext, vecColor, std::min(drawCtx->getW(), vecLength));
- }
- offsetRowContext += vecLength;
- }
- offsetContext += drawCtx->getW();
- }
- }
-
- // reinsert drawCtx into bast context
- ctx->insert(cmd->x, cmd->y, drawCtx);
-
- // remove draw context
- delete drawCtx;
- }
-
void Renderer::render(Context *ctx, std::list<std::unique_ptr<DrawCommand>> &commands)
{
if (ctx == nullptr) {
return;
}
+
for (auto &cmd : commands) {
if (cmd == nullptr) {
continue;
}
- switch (cmd->id) {
- case DrawCommandID::GUI_DRAW_CLEAR:
- ctx->fill(15);
- break;
- case DrawCommandID::GUI_DRAW_LINE:
- drawLine(ctx, static_cast<CommandLine *>(cmd.get()));
- break;
- case DrawCommandID::GUI_DRAW_RECT:
- drawRectangle(ctx, static_cast<CommandRectangle *>(cmd.get()));
- break;
- case DrawCommandID::GUI_DRAW_ARC:
- drawArc(ctx, static_cast<CommandArc *>(cmd.get()));
- break;
- case DrawCommandID::GUI_DRAW_CIRCLE:
- drawCircle(ctx, static_cast<CommandCircle *>(cmd.get()));
- break;
- case DrawCommandID::GUI_DRAW_TEXT:
- drawText(ctx, static_cast<CommandText *>(cmd.get()));
- break;
- case DrawCommandID::GUI_DRAW_IMAGE:
- drawImage(ctx, static_cast<CommandImage *>(cmd.get()));
- break;
- default:
- break;
- };
+
+ cmd->draw(ctx);
}
}
M module-gui/gui/core/Renderer.hpp => module-gui/gui/core/Renderer.hpp +0 -14
@@ 32,20 32,6 @@ namespace gui
* 3
*
*/
- protected:
- void drawLine(Context *ctx, CommandLine *cmd);
-
- void drawRectangle(Context *ctx, CommandRectangle *cmd);
-
- void drawArc(Context *ctx, CommandArc *cmd);
-
- void drawCircle(Context *ctx, CommandCircle *cmd);
-
- void drawText(Context *ctx, CommandText *cmd);
-
- void drawChar(Context *context, const int16_t x, const int16_t y, FontGlyph *glyph, const Color color);
-
- void drawImage(Context *ctx, CommandImage *cmd);
public:
virtual ~Renderer() = default;
M module-gui/gui/core/renderers/ArcRenderer.cpp => module-gui/gui/core/renderers/ArcRenderer.cpp +1 -1
@@ 8,7 8,7 @@ namespace gui::renderer
{
constexpr Length RadiusPrecisionLimit = 5;
- auto ArcRenderer::DrawableStyle::from(const CommandArc &command) -> DrawableStyle
+ auto ArcRenderer::DrawableStyle::from(const DrawArc &command) -> DrawableStyle
{
return DrawableStyle{command.width, command.borderColor};
}
M module-gui/gui/core/renderers/ArcRenderer.hpp => module-gui/gui/core/renderers/ArcRenderer.hpp +1 -1
@@ 25,7 25,7 @@ namespace gui::renderer
Length penWidth{1};
Color color{ColorFullBlack};
- static auto from(const CommandArc &command) -> DrawableStyle;
+ static auto from(const DrawArc &command) -> DrawableStyle;
};
static void draw(Context *ctx,
M module-gui/gui/core/renderers/CircleRenderer.cpp => module-gui/gui/core/renderers/CircleRenderer.cpp +1 -1
@@ 8,7 8,7 @@
namespace gui::renderer
{
- auto CircleRenderer::DrawableStyle::from(const CommandCircle &command) -> DrawableStyle
+ auto CircleRenderer::DrawableStyle::from(const DrawCircle &command) -> DrawableStyle
{
return DrawableStyle{command.width, command.borderColor, command.filled ? command.fillColor : ColorNoColor};
}
M module-gui/gui/core/renderers/CircleRenderer.hpp => module-gui/gui/core/renderers/CircleRenderer.hpp +1 -1
@@ 24,7 24,7 @@ namespace gui::renderer
Color borderColor{ColorFullBlack};
Color fillColor{ColorNoColor};
- static auto from(const CommandCircle &command) -> DrawableStyle;
+ static auto from(const DrawCircle &command) -> DrawableStyle;
};
static void draw(Context *ctx, Point center, Length radius, const DrawableStyle &style);
M module-gui/gui/core/renderers/LineRenderer.cpp => module-gui/gui/core/renderers/LineRenderer.cpp +1 -1
@@ 27,7 27,7 @@ namespace gui::renderer
}
} // namespace
- auto LineRenderer::DrawableStyle::from(const CommandLine &command) -> DrawableStyle
+ auto LineRenderer::DrawableStyle::from(const DrawLine &command) -> DrawableStyle
{
DrawableStyle details;
details.penWidth = command.penWidth;
M module-gui/gui/core/renderers/LineRenderer.hpp => module-gui/gui/core/renderers/LineRenderer.hpp +1 -1
@@ 32,7 32,7 @@ namespace gui::renderer
Color color{ColorFullBlack};
LineExpansionDirection direction = LineExpansionDirection::Down;
- static auto from(const CommandLine &command) -> DrawableStyle;
+ static auto from(const DrawLine &command) -> DrawableStyle;
DrawableStyle &setExpansionDirection(LineExpansionDirection value) noexcept
{
M module-gui/gui/core/renderers/PixelRenderer.cpp => module-gui/gui/core/renderers/PixelRenderer.cpp +0 -1
@@ 2,7 2,6 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "PixelRenderer.hpp"
-
#include "Context.hpp"
#include <cstring>
M module-gui/gui/core/renderers/RectangleRenderer.cpp => module-gui/gui/core/renderers/RectangleRenderer.cpp +1 -1
@@ 26,7 26,7 @@ namespace gui::renderer
}
} // namespace
- auto RectangleRenderer::DrawableStyle::from(const CommandRectangle &command) -> DrawableStyle
+ auto RectangleRenderer::DrawableStyle::from(const DrawRectangle &command) -> DrawableStyle
{
return DrawableStyle{command.penWidth,
command.radius,
M module-gui/gui/core/renderers/RectangleRenderer.hpp => module-gui/gui/core/renderers/RectangleRenderer.hpp +1 -1
@@ 30,7 30,7 @@ namespace gui::renderer
Color borderColor{ColorFullBlack};
Color fillColor{ColorNoColor};
- static auto from(const CommandRectangle &command) -> DrawableStyle;
+ static auto from(const DrawRectangle &command) -> DrawableStyle;
};
static void drawFlat(Context *ctx, Point position, Length width, Length height, const DrawableStyle &style);
M module-gui/gui/widgets/Arc.cpp => module-gui/gui/widgets/Arc.cpp +1 -1
@@ 106,7 106,7 @@ namespace gui
void Arc::buildDrawListImplementation(std::list<Command> &commands)
{
- auto arc = std::make_unique<CommandArc>(center, radius, start, sweep, focus ? focusPenWidth : penWidth, color);
+ auto arc = std::make_unique<DrawArc>(center, radius, start, sweep, focus ? focusPenWidth : penWidth, color);
arc->areaX = widgetArea.x;
arc->areaY = widgetArea.y;
arc->areaW = widgetArea.w;
M module-gui/gui/widgets/Circle.cpp => module-gui/gui/widgets/Circle.cpp +1 -1
@@ 77,7 77,7 @@ namespace gui
void Circle::buildDrawListImplementation(std::list<Command> &commands)
{
- auto circle = std::make_unique<CommandCircle>(
+ auto circle = std::make_unique<DrawCircle>(
center, radius, focus ? focusPenWidth : penWidth, focus ? focusBorderColor : color, isFilled, fillColor);
circle->areaX = widgetArea.x;
circle->areaY = widgetArea.y;
M module-gui/gui/widgets/Image.cpp => module-gui/gui/widgets/Image.cpp +6 -9
@@ 52,17 52,14 @@ namespace gui
void Image::buildDrawListImplementation(std::list<Command> &commands)
{
- auto img = std::make_unique<CommandImage>();
+ auto img = std::make_unique<DrawImage>();
// image
- img->x = drawArea.x;
- img->y = drawArea.y;
- img->w = drawArea.w;
- img->h = drawArea.h;
+ img->origin = {drawArea.x, drawArea.y};
// cmd part
- img->areaX = img->x;
- img->areaY = img->y;
- img->areaW = img->w;
- img->areaH = img->h;
+ img->areaX = img->origin.x;
+ img->areaY = img->origin.y;
+ img->areaW = drawArea.w;
+ img->areaH = drawArea.h;
img->imageID = this->imageMap->getID();
M module-gui/gui/widgets/Label.cpp => module-gui/gui/widgets/Label.cpp +6 -10
@@ 219,20 219,16 @@ namespace gui
{
Rect::buildDrawListImplementation(commands);
if (font != nullptr) {
- auto cmd = std::make_unique<CommandText>();
+ auto cmd = std::make_unique<DrawText>();
cmd->str = textDisplayed;
cmd->fontID = font->id;
cmd->color = textColor;
- cmd->x = drawArea.x;
- cmd->y = drawArea.y;
- cmd->w = drawArea.w;
- cmd->h = drawArea.h;
- cmd->tx = textArea.x;
- cmd->ty = textArea.y;
- cmd->tw = textArea.w;
- cmd->th = textArea.h;
- cmd->charsWidth = stringPixelWidth;
+ cmd->origin = {drawArea.x, drawArea.y};
+ cmd->width = drawArea.w;
+ cmd->height = drawArea.h;
+ cmd->textOrigin = {textArea.x, textArea.y};
+ cmd->textHeight = textArea.h;
cmd->areaX = widgetArea.x;
cmd->areaY = widgetArea.y;
M module-gui/gui/widgets/Rect.cpp => module-gui/gui/widgets/Rect.cpp +4 -5
@@ 96,12 96,11 @@ namespace gui
void Rect::buildDrawListImplementation(std::list<Command> &commands)
{
- auto rect = std::make_unique<CommandRectangle>();
+ auto rect = std::make_unique<DrawRectangle>();
- rect->x = drawArea.x;
- rect->y = drawArea.y;
- rect->w = drawArea.w;
- rect->h = drawArea.h;
+ rect->origin = {drawArea.x, drawArea.y};
+ rect->width = drawArea.w;
+ rect->height = drawArea.h;
rect->areaX = widgetArea.x;
rect->areaY = widgetArea.y;
rect->areaW = widgetArea.w;
M module-gui/gui/widgets/Window.cpp => module-gui/gui/widgets/Window.cpp +5 -6
@@ 28,10 28,10 @@ namespace gui
void Window::getRefreshArea(uint16_t &x, uint16_t &y, uint16_t &w, uint16_t &h)
{
- x = widgetArea.x;
- y = widgetArea.y;
- w = widgetArea.w;
- h = widgetArea.h;
+ x = widgetArea.x;
+ y = widgetArea.y;
+ w = widgetArea.w;
+ h = widgetArea.h;
}
bool Window::handleSwitchData(SwitchData *data)
@@ 41,8 41,7 @@ namespace gui
void Window::buildDrawListImplementation(std::list<Command> &commands)
{
- auto clearCommand = std::make_unique<DrawCommand>();
- clearCommand->id = DrawCommandID::GUI_DRAW_CLEAR;
+ auto clearCommand = std::make_unique<Clear>();
commands.emplace_back(std::move(clearCommand));
}