10#include "sml/graphics_wrapper/primitives.h"
18ColorFill::ColorFill(Sml::Color color)
21void ColorFill::fillLine(
const Sml::Vec2i& start,
const Sml::Vec2i& end,
22 const Sml::Rectangle<int32_t>& targetRegion)
const
24 Sml::Renderer::getInstance().setColor(m_Color);
26 Sml::Vec2i translatedStart = start + targetRegion.pos;
27 Sml::Vec2i translatedEnd = end + targetRegion.pos;
29 Sml::renderLine(translatedStart, translatedEnd);
32void ColorFill::fillArea(
const Sml::Rectangle<int32_t>& area,
33 const Sml::Rectangle<int32_t>& targetRegion)
const
35 Sml::Renderer::getInstance().setColor(m_Color);
37 Sml::Rectangle<int32_t> translatedArea = area;
38 translatedArea.pos += targetRegion.pos;
40 Sml::renderFilledRect(translatedArea);
43void ColorFill::fillPoint(
const Sml::Vec2i& point,
44 const Sml::Rectangle<int32_t>& targetRegion)
const
46 Sml::Renderer::getInstance().setColor(m_Color);
48 Sml::Vec2i translatedPoint = point + targetRegion.pos;
49 Sml::renderPoint(translatedPoint);
55const LinearGradientFill LinearGradientFill::RAINBOX_HORIZONTAL = {Sgl::LinearGradientFill::Direction::HORIZONTAL,
56 {{0.00, 0xFF'00'00'FF},
57 {0.15, 0xFF'FF'00'FF},
58 {0.33, 0x00'FF'00'FF},
59 {0.49, 0x00'FF'FF'FF},
60 {0.67, 0x00'00'FF'FF},
61 {0.84, 0xFF'00'FF'FF},
62 {1.00, 0xFF'00'00'FF}}};
64LinearGradientFill::Stop::Stop(
float offset, Sml::Color color)
65 : m_Offset(offset), m_Color(Sml::colorToNormalized(color)) {}
67float LinearGradientFill::Stop::getOffset()
const {
return m_Offset; }
68const Sml::Vec4f& LinearGradientFill::Stop::getColorVector()
const {
return m_Color; }
69Sml::Color LinearGradientFill::Stop::getColor()
const {
return Sml::colorFromNormalized(m_Color); }
73 return getOffset() < other.getOffset();
79LinearGradientFill::LinearGradientFill(
const std::initializer_list<Stop>& stops)
81 m_Stops.insert(m_Stops.end(), stops);
82 std::sort(m_Stops.begin(), m_Stops.end());
85LinearGradientFill::LinearGradientFill(Direction direction,
const std::initializer_list<Stop>& stops)
88 setDirection(direction);
91void LinearGradientFill::addStop(
const Stop& stop)
93 m_Stops.push_back(stop);
94 std::sort(m_Stops.begin(), m_Stops.end());
97void LinearGradientFill::setDirection(Direction direction)
99 m_Direction = direction;
102void LinearGradientFill::fillLine(
const Sml::Vec2i& start,
103 const Sml::Vec2i& end,
104 const Sml::Rectangle<int32_t>& targetRegion)
const
106 if (m_Stops.size() < 2 || start == end) {
return; }
108 int32_t x0 = (int32_t) start.x;
109 int32_t y0 = (int32_t) start.y;
110 int32_t x1 = (int32_t) end.x;
111 int32_t y1 = (int32_t) end.y;
113 int32_t dx = std::abs(x1 - x0);
114 int32_t dy = std::abs(y1 - y0);
115 int32_t sx = (x0 < x1) ? 1 : -1;
116 int32_t sy = (y0 < y1) ? 1 : -1;
117 int32_t err = dx - dy;
119 float length = Sml::length(end - start);
121 int32_t prevStop = -1;
122 int32_t nextStop = 0;
123 int32_t stops = m_Stops.size();
127 float offset = Sml::length(Sml::Vec2i(x0, y0) - start) / length;
129 if (nextStop != stops && offset >= m_Stops[nextStop].getOffset() && (nextStop + 1) != stops)
135 if (prevStop == -1 && nextStop != stops)
140 if (prevStop == stops || nextStop == stops)
145 float alpha = (offset - m_Stops[prevStop].getOffset()) / (m_Stops[nextStop].getOffset() - m_Stops[prevStop].getOffset());
146 Sml::Vec4f color = (1 - alpha) * m_Stops[prevStop].getColorVector() + alpha * m_Stops[nextStop].getColorVector();
148 Sml::Renderer::getInstance().setColor(Sml::colorFromNormalized(color));
149 Sml::renderPoint(Sml::Vec2i(x0, y0) + targetRegion.pos);
151 if ((x0 == x1) && (y0 == y1))
171void LinearGradientFill::fillArea(
const Sml::Rectangle<int32_t>& area,
172 const Sml::Rectangle<int32_t>& targetRegion)
const
174 if (m_Stops.size() < 2) {
return; }
176 if (m_Direction == Direction::HORIZONTAL)
178 for (int32_t row = 0; row < area.height; ++row)
180 fillLine(Sml::Vec2i(area.pos.x, area.pos.y + row),
181 Sml::Vec2i(area.pos.x + area.width - 1, area.pos.y + row),
187 for (int32_t column = 0; column < area.width; ++column)
189 fillLine(Sml::Vec2i(area.pos.x + column, area.pos.y),
190 Sml::Vec2i(area.pos.x + column, area.pos.y + area.height - 1),
196void LinearGradientFill::fillPoint(
const Sml::Vec2i& point,
197 const Sml::Rectangle<int32_t>& targetRegion)
const
199 if (m_Stops.size() < 2) {
return; }