1#ifndef NOVASVG_CANVAS_H
2#define NOVASVG_CANVAS_H
32using namespace render;
67 constexpr void move(
float dx,
float dy) {
x += dx;
y += dy; }
71 constexpr void scale(
float sx,
float sy) {
x *= sx;
y *= sy; }
74 constexpr float dot(
const Point& p)
const {
return x * p.
x +
y * p.
y; }
118 constexpr void expand(
float dw,
float dh) {
w += dw;
h += dh; }
122 constexpr void scale(
float sw,
float sh) {
w *= sw;
h *= sh; }
125 constexpr bool isEmpty()
const {
return w <= 0.f ||
h <= 0.f; }
126 constexpr bool isZero()
const {
return w <= 0.f &&
h <= 0.f; }
127 constexpr bool isValid()
const {
return w >= 0.f &&
h >= 0.f; }
167 constexpr Rect(
float width,
float height) :
Rect(0, 0, width, height) {}
174 constexpr void move(
float dx,
float dy) {
x += dx;
y += dy; }
178 constexpr void scale(
float sx,
float sy) {
x *= sx;
y *= sy;
w *= sx;
h *= sy; }
181 constexpr void inflate(
float dx,
float dy) {
x -= dx;
y -= dy;
w += dx * 2.f;
h += dy * 2.f; }
184 constexpr bool contains(
float px,
float py)
const {
return px >=
x && px <= x + w && py >=
y && py <=
y +
h; }
196 constexpr float right()
const {
return x +
w; }
199 constexpr bool isEmpty()
const {
return w <= 0.f ||
h <= 0.f; }
200 constexpr bool isZero()
const {
return w <= 0.f &&
h <= 0.f; }
201 constexpr bool isValid()
const {
return w >= 0.f &&
h >= 0.f; }
226 return Rect(l, t, r - l, b - t);
239 return Rect(l, t, r - l, b - t);
260 Transform(
float a,
float b,
float c,
float d,
float e,
float f);
293 bool parse(
const char* data,
size_t length);
325 void moveTo(
float x,
float y);
326 void lineTo(
float x,
float y);
327 void quadTo(
float x1,
float y1,
float x2,
float y2);
328 void cubicTo(
float x1,
float y1,
float x2,
float y2,
float x3,
float y3);
329 void arcTo(
float rx,
float ry,
float xAxisRotation,
bool largeArcFlag,
bool sweepFlag,
float x,
float y);
332 void addEllipse(
float cx,
float cy,
float rx,
float ry);
333 void addRoundRect(
float x,
float y,
float w,
float h,
float rx,
float ry);
334 void addRect(
float x,
float y,
float w,
float h);
345 bool isNull()
const {
return m_data ==
nullptr; }
348 bool parse(
const char*
data,
size_t length);
358 std::swap(m_data,
path.m_data);
361inline path_t* Path::release()
363 return std::exchange(m_data,
nullptr);
371 bool isDone()
const {
return m_index >= m_size; }
383using namespace render;
385enum class TextureType {
390enum class BlendMode {
403using DashArray = std::vector<float>;
407 explicit StrokeData(
float lineWidth = 1.f) : m_lineWidth(lineWidth) {}
409 void setLineWidth(
float lineWidth) { m_lineWidth = lineWidth; }
410 float lineWidth()
const {
return m_lineWidth; }
412 void setMiterLimit(
float miterLimit) { m_miterLimit = miterLimit; }
413 float miterLimit()
const {
return m_miterLimit; }
415 void setDashOffset(
float dashOffset) { m_dashOffset = dashOffset; }
416 float dashOffset()
const {
return m_dashOffset; }
418 void setDashArray(DashArray dashArray) { m_dashArray = std::move(dashArray); }
419 const DashArray& dashArray()
const {
return m_dashArray; }
421 void setLineCap(
LineCap lineCap) { m_lineCap = lineCap; }
422 LineCap lineCap()
const {
return m_lineCap; }
424 void setLineJoin(
LineJoin lineJoin) { m_lineJoin = lineJoin; }
425 LineJoin lineJoin()
const {
return m_lineJoin; }
429 float m_miterLimit{4.f};
430 float m_dashOffset{0.f};
433 DashArray m_dashArray;
436using GradientStop = gradient_stop_t;
437using GradientStops = std::vector<GradientStop>;
443 static std::shared_ptr<Canvas> create(
const Bitmap& bitmap);
444 static std::shared_ptr<Canvas> create(
float x,
float y,
float width,
float height);
445 static std::shared_ptr<Canvas> create(
const Rect& extents);
447 void setColor(
const Color& color);
448 void setColor(
float r,
float g,
float b,
float a);
449 void setLinearGradient(
float x1,
float y1,
float x2,
float y2,
SpreadMethod spread,
const GradientStops& stops,
const Transform& transform);
450 void setRadialGradient(
float cx,
float cy,
float r,
float fx,
float fy,
SpreadMethod spread,
const GradientStops& stops,
const Transform& transform);
451 void setTexture(
const Canvas& source, TextureType type,
float opacity,
const Transform& transform);
453 void fillPath(
const Path& path,
FillRule fillRule,
const Transform& transform);
454 void strokePath(
const Path& path,
const StrokeData& strokeData,
const Transform& transform);
456 void fillText(
const std::u32string_view&
text,
const Font& font,
const Point& origin,
const Transform& transform);
457 void strokeText(
const std::u32string_view&
text,
float strokeWidth,
const Font& font,
const Point& origin,
const Transform& transform);
459 void clipPath(
const Path& path,
FillRule clipRule,
const Transform& transform);
460 void clipRect(
const Rect& rect,
FillRule clipRule,
const Transform& transform);
462 void drawImage(
const Bitmap& image,
const Rect& dstRect,
const Rect& srcRect,
const Transform& transform);
463 void blendCanvas(
const Canvas& canvas, BlendMode blendMode,
float opacity);
468 void convertToLuminanceMask();
475 void boxBlur(
float stdDeviationX,
float stdDeviationY);
480 void compositeDropShadowUnder(
const Canvas& original,
float dx,
float dy);
484 void tintToFloodColor(
const Color& floodColor,
float floodOpacity);
488 void fillOpaqueWhite();
492 void shift(
float dx,
float dy);
496 enum class PorterDuff { Over,
In, Out, Atop, Xor };
497 void compositeWith(
const Canvas& src, PorterDuff mode);
498 void compositeOver(
const Canvas& src) ;
504 void compositeArithmetic(
const Canvas& src,
float k1,
float k2,
float k3,
float k4);
508 void copyPixelsFrom(
const Canvas& other);
510 int x()
const {
return m_x; }
511 int y()
const {
return m_y; }
515 Rect extents()
const {
return Rect(m_x, m_y, width(), height()); }
517 surface_t* surface()
const {
return m_surface; }
518 canvas_t* canvas()
const {
return m_canvas; }
523 Canvas(
const Bitmap& bitmap);
524 Canvas(
int x,
int y,
int width,
int height);
540using namespace render;
579 return (*
this = *
this * transform);
584 return (*
this *= transform);
609 return (*
this = transform * *
this);
663 if(!
rect.isValid()) {
674 return std::sqrt(m_matrix.
a * m_matrix.
a + m_matrix.
b * m_matrix.
b);
679 return std::sqrt(m_matrix.
c * m_matrix.
c + m_matrix.
d * m_matrix.
d);
690 if(cx == 0.f && cy == 0.f) {
728 : m_data(
path.release())
811 if(m_data ==
nullptr)
823 if(m_data ==
nullptr)
871 points[0] = m_elements[m_index + 1].
point;
874 points[0] = m_elements[m_index + 1].
point;
877 points[0] = m_elements[m_index + 1].
point;
878 points[1] = m_elements[m_index + 2].
point;
879 points[2] = m_elements[m_index + 3].
point;
882 points[0] = m_elements[m_index + 1].
point;
897 return std::shared_ptr<Canvas>(
new Canvas(bitmap));
900NOVASVG_INLINE std::shared_ptr<Canvas> Canvas::create(
float x,
float y,
float width,
float height)
902 constexpr int kMaxSize = 1 << 15;
903 if(width <= 0 || height <= 0 || width >= kMaxSize || height >= kMaxSize)
904 return std::shared_ptr<Canvas>(
new Canvas(0, 0, 1, 1));
905 auto l =
static_cast<int>(std::floor(x));
906 auto t =
static_cast<int>(std::floor(y));
907 auto r =
static_cast<int>(std::ceil(x + width));
908 auto b =
static_cast<int>(std::ceil(y + height));
909 return std::shared_ptr<Canvas>(
new Canvas(l, t, r - l, b - t));
912NOVASVG_INLINE std::shared_ptr<Canvas> Canvas::create(
const Rect& extents)
914 return create(extents.x, extents.y, extents.w, extents.h);
919 setColor(color.getRF(), color.getGF(), color.getBF(), color.getAF());
922NOVASVG_INLINE void Canvas::setColor(
float r,
float g,
float b,
float a)
927NOVASVG_INLINE void Canvas::setLinearGradient(
float x1,
float y1,
float x2,
float y2,
SpreadMethod spread,
const GradientStops& stops,
const Transform& transform)
932NOVASVG_INLINE void Canvas::setRadialGradient(
float cx,
float cy,
float r,
float fx,
float fy,
SpreadMethod spread,
const GradientStops& stops,
const Transform& transform)
934 canvas_set_radial_gradient(m_canvas, cx, cy, r, fx, fy, 0.f,
static_cast<spread_method_t>(spread), stops.data(), stops.size(), &transform.matrix());
937NOVASVG_INLINE void Canvas::setTexture(
const Canvas& source, TextureType type,
float opacity,
const Transform& transform)
951NOVASVG_INLINE void Canvas::strokePath(
const Path& path,
const StrokeData& strokeData,
const Transform& transform)
965NOVASVG_INLINE void Canvas::fillText(
const std::u32string_view&
text,
const Font& font,
const Point& origin,
const Transform& transform)
975NOVASVG_INLINE void Canvas::strokeText(
const std::u32string_view&
text,
float strokeWidth,
const Font& font,
const Point& origin,
const Transform& transform)
1006NOVASVG_INLINE void Canvas::drawImage(
const Bitmap& image,
const Rect& dstRect,
const Rect& srcRect,
const Transform& transform)
1008 auto xScale = dstRect.w / srcRect.w;
1009 auto yScale = dstRect.h / srcRect.h;
1010 matrix_t matrix = { xScale, 0, 0, yScale, -srcRect.x * xScale, -srcRect.y * yScale };
1020NOVASVG_INLINE void Canvas::blendCanvas(
const Canvas& canvas, BlendMode blendMode,
float opacity)
1022 matrix_t matrix = { 1, 0, 0, 1,
static_cast<float>(canvas.x()),
static_cast<float>(canvas.y()) };
1055 for(
int y = 0; y < height; y++) {
1056 auto pixels =
reinterpret_cast<uint32_t*
>(data + stride * y);
1057 for(
int x = 0; x < width; x++) {
1058 auto pixel = pixels[x];
1059 auto a = (pixel >> 24) & 0xFF;
1060 auto r = (pixel >> 16) & 0xFF;
1061 auto g = (pixel >> 8) & 0xFF;
1062 auto b = (pixel >> 0) & 0xFF;
1069 auto l = (r * 0.2125 + g * 0.7154 + b * 0.0721);
1070 pixels[x] =
static_cast<uint32_t
>(l * (a / 255.0)) << 24;
1086static void boxBlurPass(
unsigned char* data,
int width,
int height,
int stride,
int radius,
bool horizontal)
1088 if(radius <= 0 || width <= 0 || height <= 0)
1090 auto* scratch =
static_cast<unsigned char*
>(malloc(
size_t(stride) *
size_t(height)));
1093 memcpy(scratch, data,
size_t(stride) *
size_t(height));
1095 const float iarr = 1.f / float(radius * 2 + 1);
1096 auto pack = [iarr](int32_t a, int32_t r, int32_t g, int32_t b) {
1097 return (uint32_t(
float(a) * iarr) << 24) | (uint32_t(
float(r) * iarr) << 16) | (uint32_t(
float(g) * iarr) << 8)
1098 | uint32_t(
float(b) * iarr);
1102 for(
int y = 0; y < height; ++y) {
1103 const auto* in =
reinterpret_cast<const uint32_t*
>(scratch + size_t(y) * size_t(stride));
1104 auto* out =
reinterpret_cast<uint32_t*
>(data + size_t(y) * size_t(stride));
1105 auto at = [in, width](
int x) {
return in[x < 0 ? 0 : (x >= width ? width - 1 : x)]; };
1107 int32_t a = 0, r = 0, g = 0, b = 0;
1108 for(
int k = -radius; k <= radius; ++k) {
1109 const uint32_t pixel = at(k);
1110 a += (pixel >> 24) & 0xFF;
1111 r += (pixel >> 16) & 0xFF;
1112 g += (pixel >> 8) & 0xFF;
1116 for(
int x = 0; x < width; ++x) {
1117 out[x] = pack(a, r, g, b);
1118 const uint32_t leaving = at(x - radius);
1119 const uint32_t entering = at(x + radius + 1);
1120 a += int32_t((entering >> 24) & 0xFF) - int32_t((leaving >> 24) & 0xFF);
1121 r += int32_t((entering >> 16) & 0xFF) - int32_t((leaving >> 16) & 0xFF);
1122 g += int32_t((entering >> 8) & 0xFF) - int32_t((leaving >> 8) & 0xFF);
1123 b += int32_t(entering & 0xFF) - int32_t(leaving & 0xFF);
1128 std::vector<int32_t> sums(
size_t(width) * 4, 0);
1129 auto row = [&](
int y) {
1130 y = y < 0 ? 0 : (y >= height ? height - 1 : y);
1131 return reinterpret_cast<const uint32_t*
>(scratch + size_t(y) * size_t(stride));
1134 for(
int k = -radius; k <= radius; ++k) {
1135 const uint32_t* p = row(k);
1136 for(
int x = 0; x < width; ++x) {
1137 const uint32_t pixel = p[x];
1138 sums[size_t(x) * 4 + 0] += (pixel >> 24) & 0xFF;
1139 sums[size_t(x) * 4 + 1] += (pixel >> 16) & 0xFF;
1140 sums[size_t(x) * 4 + 2] += (pixel >> 8) & 0xFF;
1141 sums[size_t(x) * 4 + 3] += pixel & 0xFF;
1145 for(
int y = 0; y < height; ++y) {
1146 auto* out =
reinterpret_cast<uint32_t*
>(data + size_t(y) * size_t(stride));
1147 const uint32_t* leaving = row(y - radius);
1148 const uint32_t* entering = row(y + radius + 1);
1149 for(
int x = 0; x < width; ++x) {
1150 int32_t* sum = &sums[size_t(x) * 4];
1151 out[x] = pack(sum[0], sum[1], sum[2], sum[3]);
1152 const uint32_t lp = leaving[x], ep = entering[x];
1153 sum[0] += int32_t((ep >> 24) & 0xFF) - int32_t((lp >> 24) & 0xFF);
1154 sum[1] += int32_t((ep >> 16) & 0xFF) - int32_t((lp >> 16) & 0xFF);
1155 sum[2] += int32_t((ep >> 8) & 0xFF) - int32_t((lp >> 8) & 0xFF);
1156 sum[3] += int32_t(ep & 0xFF) - int32_t(lp & 0xFF);
1174static int gaussianRadiusForSigma(
float sigma)
1178 auto d = sigma * 3.f * std::sqrt(2.f * 3.14159265f) / 4.f;
1182NOVASVG_INLINE void Canvas::boxBlur(
float stdDeviationX,
float stdDeviationY)
1189 auto rx = gaussianRadiusForSigma(stdDeviationX);
1190 auto ry = gaussianRadiusForSigma(stdDeviationY);
1191 for(
int pass = 0; pass < 3; ++pass) {
1192 if(rx > 0) boxBlurPass(data, width, height, stride, rx,
true);
1193 if(ry > 0) boxBlurPass(data, width, height, stride, ry,
false);
1203 for(
int y = 0; y < height; ++y) {
1204 auto* pixels =
reinterpret_cast<uint32_t*
>(data + stride * y);
1205 for(
int x = 0; x < width; ++x)
1206 pixels[x] = 0xFFFFFFFFu;
1210NOVASVG_INLINE void Canvas::tintToFloodColor(
const Color& floodColor,
float floodOpacity)
1217 auto r = uint32_t(floodColor.getR());
1218 auto g = uint32_t(floodColor.getG());
1219 auto b = uint32_t(floodColor.getB());
1220 for(
int y = 0; y < height; ++y) {
1221 auto* pixels =
reinterpret_cast<uint32_t*
>(data + stride * y);
1222 for(
int x = 0; x < width; ++x) {
1223 auto srcAlpha = (pixels[x] >> 24) & 0xFF;
1224 auto alpha = uint32_t(srcAlpha * floodOpacity);
1226 pixels[x] = (alpha << 24) | (((r * alpha) / 255) << 16) | (((g * alpha) / 255) << 8) | ((b * alpha) / 255);
1239 if(idx == 0 && idy == 0)
1242 auto* scratch =
static_cast<unsigned char*
>(malloc(
size_t(stride) *
size_t(height)));
1245 memset(scratch, 0,
size_t(stride) *
size_t(height));
1246 for(
int y = 0; y < height; ++y) {
1248 if(sy < 0 || sy >= height)
continue;
1249 auto* src =
reinterpret_cast<uint32_t*
>(data + sy * stride);
1250 auto* dst =
reinterpret_cast<uint32_t*
>(scratch + y * stride);
1251 for(
int x = 0; x < width; ++x) {
1253 if(sx < 0 || sx >= width)
continue;
1257 memcpy(data, scratch,
size_t(stride) *
size_t(height));
1261NOVASVG_INLINE void Canvas::compositeWith(
const Canvas& src, PorterDuff mode)
1273 for(
int y = 0; y < height && y < sHeight; ++y) {
1274 auto* dst =
reinterpret_cast<uint32_t*
>(data + y * stride);
1275 auto* srcRow =
reinterpret_cast<uint32_t*
>(sData + y * sStride);
1276 for(
int x = 0; x < width && x < sWidth; ++x) {
1279 auto sA = (s >> 24) & 0xFF;
1280 auto dA = (d >> 24) & 0xFF;
1285 case PorterDuff::In: Fs = dA; Fd = 0;
break;
1286 case PorterDuff::Out: Fs = 255 - dA; Fd = 0;
break;
1287 case PorterDuff::Atop: Fs = dA; Fd = 255 - sA;
break;
1288 case PorterDuff::Xor: Fs = 255 - dA; Fd = 255 - sA;
break;
1289 case PorterDuff::Over:
default: Fs = 255; Fd = 255 - sA;
break;
1292 auto sr = (s >> 16) & 0xFF, sg = (s >> 8) & 0xFF, sb = s & 0xFF;
1293 auto dr = (d >> 16) & 0xFF, dg = (d >> 8) & 0xFF, db = d & 0xFF;
1294 auto outA =
NOVASVG_MIN(255,
int(sA * Fs + dA * Fd) / 255);
1295 auto outR =
NOVASVG_MIN(255,
int(sr * Fs + dr * Fd) / 255);
1296 auto outG =
NOVASVG_MIN(255,
int(sg * Fs + dg * Fd) / 255);
1297 auto outB =
NOVASVG_MIN(255,
int(sb * Fs + db * Fd) / 255);
1298 dst[x] = (uint32_t(outA) << 24) | (uint32_t(outR) << 16) | (uint32_t(outG) << 8) | uint32_t(outB);
1305 compositeWith(src, PorterDuff::Over);
1308NOVASVG_INLINE void Canvas::compositeArithmetic(
const Canvas& src,
float k1,
float k2,
float k3,
float k4)
1320 auto solve = [&](
int i1,
int i2) ->
int {
1321 auto f1 = float(i1) / 255.f;
1322 auto f2 = float(i2) / 255.f;
1323 auto result = k1 * f1 * f2 + k2 * f1 + k3 * f2 + k4;
1324 return int(std::clamp(result, 0.f, 1.f) * 255.f + 0.5f);
1327 for(
int y = 0; y < height; ++y) {
1328 auto* dst =
reinterpret_cast<uint32_t*
>(data + y * stride);
1329 auto* srcRow = y < sHeight ? reinterpret_cast<uint32_t*>(sData + y * sStride) : nullptr;
1330 for(
int x = 0; x < width; ++x) {
1331 auto s = (srcRow && x < sWidth) ? srcRow[x] : 0u;
1333 auto outA = solve((s >> 24) & 0xFF, (d >> 24) & 0xFF);
1334 auto outR = solve((s >> 16) & 0xFF, (d >> 16) & 0xFF);
1335 auto outG = solve((s >> 8) & 0xFF, (d >> 8) & 0xFF);
1336 auto outB = solve(s & 0xFF, d & 0xFF);
1337 dst[x] = (uint32_t(outA) << 24) | (uint32_t(outR) << 16) | (uint32_t(outG) << 8) | uint32_t(outB);
1342NOVASVG_INLINE void Canvas::compositeDropShadowUnder(
const Canvas& original,
float dx,
float dy)
1345 compositeOver(original);
1364 , m_translation({1, 0, 0, 1, 0, 0})
1369NOVASVG_INLINE Canvas::Canvas(
int x,
int y,
int width,
int height)
1372 , m_translation({1, 0, 0, 1, -
static_cast<float>(x), -
static_cast<float>(y)})
Represents a 2D axis-aligned bounding box.
Represents a 2D transformation matrix.
PathCommand currentSegment(std::array< Point, 3 > &points) const
PathIterator(const Path &path)
void arcTo(float rx, float ry, float xAxisRotation, bool largeArcFlag, bool sweepFlag, float x, float y)
Rect boundingRect() const
Path & operator=(const Path &path)
void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
void lineTo(float x, float y)
void addRect(float x, float y, float w, float h)
void quadTo(float x1, float y1, float x2, float y2)
void moveTo(float x, float y)
void addRoundRect(float x, float y, float w, float h, float rx, float ry)
bool parse(const char *data, size_t length)
void addEllipse(float cx, float cy, float rx, float ry)
constexpr void move(const Point &p)
constexpr void scale(float s)
constexpr Point(float x, float y)
constexpr float dot(const Point &p) const
constexpr Point()=default
constexpr void scale(float sx, float sy)
constexpr void move(float d)
constexpr void move(float dx, float dy)
constexpr Point(const point_t &point)
constexpr Rect(const Size &size)
constexpr bool contains(float px, float py) const
constexpr float right() const
constexpr void inflate(float d)
constexpr bool isValid() const
constexpr Rect(const rect_t &rect)
constexpr void scale(float sx, float sy)
constexpr Rect & unite(const Rect &o)
constexpr Rect(const Point &origin, const Size &size)
constexpr bool contains(const Point &p) const
static const Rect Infinite
constexpr Rect intersected(const Rect &rect) const
constexpr void move(float d)
constexpr void move(float dx, float dy)
constexpr Rect(float x, float y, float w, float h)
constexpr void move(const Point &p)
constexpr bool isZero() const
constexpr Size size() const
constexpr float bottom() const
constexpr void scale(float s)
constexpr Rect & intersect(const Rect &o)
constexpr Rect united(const Rect &rect) const
constexpr void inflate(float dx, float dy)
constexpr bool isEmpty() const
constexpr Point origin() const
static const Rect Invalid
constexpr Rect(float width, float height)
constexpr void expand(const Size &s)
constexpr bool isValid() const
constexpr void expand(float dw, float dh)
constexpr bool isEmpty() const
constexpr Size(float w, float h)
constexpr void scale(float s)
constexpr bool isZero() const
constexpr void scale(float sw, float sh)
constexpr void expand(float d)
#define NOVASVG_MAX(a, b)
#define NOVASVG_MIN(a, b)
NOVASVG_INLINE void matrix_map(const matrix_t *matrix, float x, float y, float *xx, float *yy)
Transforms the point (x, y) using matrix and stores the result in (xx, yy).
NOVASVG_INLINE path_t * path_create(void)
Creates a new path object.
@ NOVASVG_PATH_COMMAND_CUBIC_TO
Draws a cubic Bézier curve to a new point.
@ NOVASVG_PATH_COMMAND_CLOSE
Closes the current path by drawing a line to the starting point.
@ NOVASVG_PATH_COMMAND_LINE_TO
Draws a straight line to a new point.
@ NOVASVG_PATH_COMMAND_MOVE_TO
Moves the current point to a new position.
NOVASVG_INLINE void canvas_set_rgba(canvas_t *canvas, float r, float g, float b, float a)
Sets the current paint to a solid color.
texture_type_t
Defines the type of texture, either plain or tiled.
@ NOVASVG_TEXTURE_TYPE_TILED
Tiled texture.
@ NOVASVG_TEXTURE_TYPE_PLAIN
Plain texture.
NOVASVG_INLINE void canvas_fill_rect(canvas_t *canvas, float x, float y, float w, float h)
Fills a rectangle according to the current fill rule.
struct novasvg::render::matrix matrix_t
A structure representing a 2D transformation matrix.
NOVASVG_INLINE void canvas_set_matrix(canvas_t *canvas, const matrix_t *matrix)
Resets the current transformation matrix to the specified matrix.
NOVASVG_INLINE void canvas_destroy(canvas_t *canvas)
Decreases the reference count and destroys the canvas when it reaches zero.
NOVASVG_INLINE void path_move_to(path_t *path, float x, float y)
Moves the current point to a new position.
NOVASVG_INLINE void canvas_set_line_join(canvas_t *canvas, line_join_t line_join)
Sets the line join style.
NOVASVG_INLINE void matrix_init_rotate(matrix_t *matrix, float angle)
Initializes a 2D transformation matrix for rotation.
NOVASVG_INLINE void path_arc_to(path_t *path, float rx, float ry, float angle, bool large_arc_flag, bool sweep_flag, float x, float y)
Adds an elliptical arc to the path.
NOVASVG_INLINE void path_cubic_to(path_t *path, float x1, float y1, float x2, float y2, float x3, float y3)
Adds a cubic Bézier curve to the path.
int surface_get_width(const surface_t *surface)
Gets the width of the surface.
NOVASVG_INLINE float path_extents(const path_t *path, rect_t *extents, bool tight)
Computes the bounding box and total length of the path.
struct surface surface_t
Represents an image surface for drawing operations.
NOVASVG_INLINE void canvas_stroke_path(canvas_t *canvas, const path_t *path)
Strokes a path with the current stroke settings.
int surface_get_height(const surface_t *surface)
Gets the height of the surface.
NOVASVG_INLINE void canvas_save(canvas_t *canvas)
Saves the current state of the canvas.
NOVASVG_INLINE float canvas_stroke_text(canvas_t *canvas, const void *text, int length, text_encoding_t encoding, float x, float y)
Strokes a text at the specified origin.
NOVASVG_INLINE void path_destroy(path_t *path)
Decreases the reference count of a path object.
NOVASVG_INLINE void path_close(path_t *path)
Closes the current sub-path.
NOVASVG_INLINE void canvas_set_dash_offset(canvas_t *canvas, float offset)
Sets the dash offset.
int surface_get_stride(const surface_t *surface)
Gets the stride of the surface.
surface_t * surface_create(int width, int height)
Creates a new image surface with the specified dimensions.
NOVASVG_INLINE bool path_parse(path_t *path, const char *data, int length)
Parses SVG path data into a path_t object.
NOVASVG_INLINE void canvas_set_fill_rule(canvas_t *canvas, fill_rule_t winding)
Sets the fill rule.
void surface_destroy(surface_t *surface)
Decrements the reference count and destroys the surface if the count reaches zero.
NOVASVG_INLINE void matrix_init_identity(matrix_t *matrix)
Initializes a 2D transformation matrix to the identity matrix.
NOVASVG_INLINE bool matrix_parse(matrix_t *matrix, const char *data, int length)
Parses an SVG transform string into a matrix.
NOVASVG_INLINE void canvas_set_radial_gradient(canvas_t *canvas, float cx, float cy, float cr, float fx, float fy, float fr, spread_method_t spread, const gradient_stop_t *stops, int nstops, const matrix_t *matrix)
Sets the current paint to a radial gradient.
line_join_t
Defines the shape used at the corners of paths.
@ NOVASVG_LINE_JOIN_BEVEL
Beveled join with a flattened corner.
@ NOVASVG_LINE_JOIN_MITER
Miter join with sharp corners.
@ NOVASVG_LINE_JOIN_ROUND
Rounded join.
NOVASVG_INLINE path_t * path_reference(path_t *path)
Increases the reference count of a path object.
fill_rule_t
Defines fill rule types for filling paths.
@ NOVASVG_FILL_RULE_NON_ZERO
Non-zero winding fill rule.
@ NOVASVG_FILL_RULE_EVEN_ODD
Even-odd fill rule.
NOVASVG_INLINE canvas_t * canvas_create(surface_t *surface)
Creates a drawing context on a surface.
NOVASVG_INLINE void matrix_init_scale(matrix_t *matrix, float sx, float sy)
Initializes a 2D transformation matrix for scaling.
NOVASVG_INLINE bool matrix_invert(const matrix_t *matrix, matrix_t *inverse)
Calculates the inverse of matrix and stores it in inverse.
NOVASVG_INLINE void path_add_ellipse(path_t *path, float cx, float cy, float rx, float ry)
Adds an ellipse to the path.
NOVASVG_INLINE void canvas_paint(canvas_t *canvas)
A drawing operator that paints the current clipping region using the current paint.
NOVASVG_INLINE void canvas_fill_path(canvas_t *canvas, const path_t *path)
Fills a path according to the current fill rule.
NOVASVG_INLINE void path_quad_to(path_t *path, float x1, float y1, float x2, float y2)
Adds a quadratic Bézier curve to the path.
NOVASVG_INLINE void canvas_translate(canvas_t *canvas, float tx, float ty)
Translates the current transformation matrix by offsets tx and ty.
line_cap_t
Defines the shape used at the ends of open subpaths.
@ NOVASVG_LINE_CAP_SQUARE
Square ends at the end of the stroke.
@ NOVASVG_LINE_CAP_ROUND
Rounded ends at the end of the stroke.
@ NOVASVG_LINE_CAP_BUTT
Flat edge at the end of the stroke.
NOVASVG_INLINE void canvas_transform(canvas_t *canvas, const matrix_t *matrix)
Multiplies the current transformation matrix with the specified matrix.
NOVASVG_INLINE void path_reset(path_t *path)
Resets the path.
NOVASVG_INLINE void path_add_round_rect(path_t *path, float x, float y, float w, float h, float rx, float ry)
Adds a rounded rectangle to the path.
NOVASVG_INLINE void canvas_set_texture(canvas_t *canvas, surface_t *surface, texture_type_t type, float opacity, const matrix_t *matrix)
Sets the current paint to a texture.
operator_t
Defines compositing operations.
@ NOVASVG_OPERATOR_DST_IN
Destination within source.
@ NOVASVG_OPERATOR_EXCLUSION
Like difference, with lower contrast.
@ NOVASVG_OPERATOR_SRC
Source replaces destination.
@ NOVASVG_OPERATOR_MULTIPLY
Backdrop * source: darkens, white is neutral.
@ NOVASVG_OPERATOR_LIGHTEN
The lighter of backdrop and source, per channel.
@ NOVASVG_OPERATOR_DST_OUT
Destination outside source.
@ NOVASVG_OPERATOR_DARKEN
The darker of backdrop and source, per channel.
@ NOVASVG_OPERATOR_SRC_OVER
Source is composited over destination.
@ NOVASVG_OPERATOR_DIFFERENCE
Absolute difference of backdrop and source, per channel.
@ NOVASVG_OPERATOR_SCREEN
Inverse of multiply: lightens, black is neutral.
@ NOVASVG_TEXT_ENCODING_UTF32
UTF-32 encoding.
NOVASVG_INLINE void canvas_set_miter_limit(canvas_t *canvas, float miter_limit)
Sets the miter limit.
NOVASVG_INLINE void canvas_set_operator(canvas_t *canvas, operator_t op)
Sets the compositing operator.
NOVASVG_INLINE void canvas_set_linear_gradient(canvas_t *canvas, float x1, float y1, float x2, float y2, spread_method_t spread, const gradient_stop_t *stops, int nstops, const matrix_t *matrix)
Sets the current paint to a linear gradient.
NOVASVG_INLINE int path_get_reference_count(const path_t *path)
Retrieves the reference count of a path object.
NOVASVG_INLINE void canvas_set_line_width(canvas_t *canvas, float line_width)
Sets the line width.
NOVASVG_INLINE void canvas_set_line_cap(canvas_t *canvas, line_cap_t line_cap)
Sets the line cap style.
NOVASVG_INLINE void path_line_to(path_t *path, float x, float y)
Adds a straight line segment to the path.
NOVASVG_INLINE void matrix_init_shear(matrix_t *matrix, float shx, float shy)
Initializes a 2D transformation matrix for shearing.
NOVASVG_INLINE void matrix_multiply(matrix_t *matrix, const matrix_t *left, const matrix_t *right)
Multiplies left and right matrices and stores the result in matrix.
spread_method_t
Defines the spread method for gradients.
@ NOVASVG_SPREAD_METHOD_PAD
Pad the gradient's edges.
@ NOVASVG_SPREAD_METHOD_REFLECT
Reflect the gradient beyond its bounds.
@ NOVASVG_SPREAD_METHOD_REPEAT
Repeat the gradient pattern.
NOVASVG_INLINE void matrix_rotate(matrix_t *matrix, float angle)
Rotates the matrix by the specified angle (in radians).
struct canvas canvas_t
Represents a drawing context.
NOVASVG_INLINE void canvas_set_font(canvas_t *canvas, font_face_t *face, float size)
Sets the font face and size for text rendering on the canvas.
NOVASVG_INLINE void canvas_restore(canvas_t *canvas)
Restores the canvas to the most recently saved state.
NOVASVG_INLINE void matrix_init(matrix_t *matrix, float a, float b, float c, float d, float e, float f)
Initializes a 2D transformation matrix.
surface_t * surface_reference(surface_t *surface)
Increments the reference count for a surface.
NOVASVG_INLINE void canvas_set_dash_array(canvas_t *canvas, const float *dashes, int ndashes)
Sets the dash pattern.
NOVASVG_INLINE void matrix_init_translate(matrix_t *matrix, float tx, float ty)
Initializes a 2D transformation matrix for translation.
NOVASVG_INLINE float canvas_fill_text(canvas_t *canvas, const void *text, int length, text_encoding_t encoding, float x, float y)
Fills a text at the specified origin.
NOVASVG_INLINE void matrix_translate(matrix_t *matrix, float tx, float ty)
Adds a translation with offsets tx and ty to the matrix.
NOVASVG_INLINE path_t * path_clone(const path_t *path)
Creates a copy of the path.
NOVASVG_INLINE void matrix_map_rect(const matrix_t *matrix, const rect_t *src, rect_t *dst)
Transforms the src rectangle using matrix and stores the result in dst.
NOVASVG_INLINE int path_get_elements(const path_t *path, const path_element_t **elements)
Retrieves the elements of a path.
NOVASVG_INLINE void canvas_clip_path(canvas_t *canvas, const path_t *path)
Intersects the current clipping region with a path according to the current fill rule.
NOVASVG_INLINE void path_add_rect(path_t *path, float x, float y, float w, float h)
Adds a rectangle to the path.
NOVASVG_INLINE void canvas_clip_rect(canvas_t *canvas, float x, float y, float w, float h)
Intersects the current clipping region with a rectangle according to the current fill rule.
unsigned char * surface_get_data(const surface_t *surface)
Gets the pixel data of the surface.
Main namespace for the NovaSVG library.
constexpr Point & operator-=(Point &a, const Point &b)
constexpr Point & operator+=(Point &a, const Point &b)
constexpr float operator*(const Point &a, const Point &b)
constexpr Point operator-(const Point &a, const Point &b)
constexpr Point operator+(const Point &a, const Point &b)
#define NOVASVG_DEG2RAD(x)
A structure representing a 2D transformation matrix.
float d
The vertical scaling factor.
float c
The horizontal shearing factor.
float b
The vertical shearing factor.
float a
The horizontal scaling factor.
A structure representing a point in 2D space.
float y
The y-coordinate of the point.
float x
The x-coordinate of the point.
A structure representing a rectangle in 2D space.
float x
The x-coordinate of the top-left corner of the rectangle.
float w
The width of the rectangle.
float h
The height of the rectangle.
float y
The y-coordinate of the top-left corner of the rectangle.
std::string text
UTF-8; ' ' marks a forced line break ( ,.
point_t point
A coordinate point in the path.
struct novasvg::render::path_element::@14 header
Header for path commands.
int length
Number of elements including the header.
path_command_t command
The path command.