6#include "vendor/ft_raster.h"
7#include "vendor/ft_stroker.h"
25 for(
int i = 0; i < height; i++) {
34 span_buffer->
w = width;
35 span_buffer->
h = height;
57 span_buffer->
x = source->
x;
58 span_buffer->
y = source->
y;
59 span_buffer->
w = source->
w;
60 span_buffer->
h = source->
h;
65 const int ix = (int)floorf(x);
66 const int iy = (int)floorf(y);
68 for(
int i = 0; i < span_buffer->
spans.
size; i++) {
72 if(ix >= span->
x && ix < (span->
x + span->
len)) {
82 if(span_buffer->
w != -1 && span_buffer->
h != -1)
97 for(
int i = 0; i < span_buffer->
spans.
size; i++) {
98 if(spans[i].x < x1) x1 = spans[i].
x;
99 if(spans[i].x + spans[i].len > x2) x2 = spans[i].
x + spans[i].
len;
104 span_buffer->
w = x2 - x1;
105 span_buffer->
h = y2 - y1 + 1;
111 extents->
x = span_buffer->
x;
112 extents->
y = span_buffer->
y;
113 extents->
w = span_buffer->
w;
114 extents->
h = span_buffer->
h;
127 while(a_spans < a_end && b_spans < b_end) {
128 if(b_spans->
y > a_spans->
y) {
133 if(a_spans->
y != b_spans->
y) {
138 int ax1 = a_spans->
x;
139 int ax2 = ax1 + a_spans->
len;
140 int bx1 = b_spans->
x;
141 int bx2 = bx1 + b_spans->
len;
142 if(bx1 < ax1 && bx2 < ax1) {
147 if(ax1 < bx1 && ax2 < bx1) {
159 span->
y = a_spans->
y;
172#define ALIGN_SIZE(size) (((size) + 7ul) & ~7ul)
175 size_t points_size =
ALIGN_SIZE((points + contours) *
sizeof(PVG_FT_Vector));
176 size_t tags_size =
ALIGN_SIZE((points + contours) *
sizeof(
char));
177 size_t contours_size =
ALIGN_SIZE(contours *
sizeof(
int));
178 size_t contours_flag_size =
ALIGN_SIZE(contours *
sizeof(
char));
179 PVG_FT_Outline* outline =
static_cast<PVG_FT_Outline*
>(malloc(points_size + tags_size + contours_size + contours_flag_size +
sizeof(PVG_FT_Outline)));
181 PVG_FT_Byte* outline_data = (PVG_FT_Byte*)(outline + 1);
182 outline->points = (PVG_FT_Vector*)(outline_data);
183 outline->tags = (
char*)(outline_data + points_size);
184 outline->contours = (
int*)(outline_data + points_size + tags_size);
185 outline->contours_flag = (
char*)(outline_data + points_size + tags_size + contours_size);
186 outline->n_points = 0;
187 outline->n_contours = 0;
188 outline->flags = 0x0;
202 if(!(v > -1e9f && v < 1e9f))
203 return (PVG_FT_Pos)roundf(v);
204 const int t = int(v);
205 const float diff = v - float(t);
207 return PVG_FT_Pos(t) + 1;
209 return PVG_FT_Pos(t) - 1;
210 return PVG_FT_Pos(t);
213#define FT_COORD(x) ft_coord_round((x) * 64)
216 ft->points[ft->n_points].x =
FT_COORD(x);
217 ft->points[ft->n_points].y =
FT_COORD(y);
218 ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_ON;
220 ft->contours[ft->n_contours] = ft->n_points - 1;
224 ft->contours_flag[ft->n_contours] = 1;
230 ft->points[ft->n_points].x =
FT_COORD(x);
231 ft->points[ft->n_points].y =
FT_COORD(y);
232 ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_ON;
238 ft->points[ft->n_points].x =
FT_COORD(x1);
239 ft->points[ft->n_points].y =
FT_COORD(y1);
240 ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_CUBIC;
243 ft->points[ft->n_points].x =
FT_COORD(x2);
244 ft->points[ft->n_points].y =
FT_COORD(y2);
245 ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_CUBIC;
248 ft->points[ft->n_points].x =
FT_COORD(x3);
249 ft->points[ft->n_points].y =
FT_COORD(y3);
250 ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_ON;
256 ft->contours_flag[ft->n_contours] = 0;
257 int index = ft->n_contours ? ft->contours[ft->n_contours - 1] + 1 : 0;
258 if(index == ft->n_points)
260 ft->points[ft->n_points].x = ft->points[index].x;
261 ft->points[ft->n_points].y = ft->points[index].y;
262 ft->tags[ft->n_points] = PVG_FT_CURVE_TAG_ON;
269 ft->contours[ft->n_contours] = ft->n_points - 1;
299 ft_outline_cubic_to(outline, points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y);
327 double width = stroke_data->
style.
width * scale;
329 PVG_FT_Fixed ftWidth = (PVG_FT_Fixed)(width * 0.5 * (1 << 6));
330 PVG_FT_Fixed ftMiterLimit = (PVG_FT_Fixed)(stroke_data->
style.
miter_limit * (1 << 16));
332 PVG_FT_Stroker_LineCap ftCap;
335 ftCap = PVG_FT_STROKER_LINECAP_SQUARE;
338 ftCap = PVG_FT_STROKER_LINECAP_ROUND;
341 ftCap = PVG_FT_STROKER_LINECAP_BUTT;
345 PVG_FT_Stroker_LineJoin ftJoin;
348 ftJoin = PVG_FT_STROKER_LINEJOIN_BEVEL;
351 ftJoin = PVG_FT_STROKER_LINEJOIN_ROUND;
354 ftJoin = PVG_FT_STROKER_LINEJOIN_MITER_FIXED;
358 PVG_FT_Stroker stroker;
359 PVG_FT_Stroker_New(&stroker);
360 PVG_FT_Stroker_Set(stroker, ftWidth, ftCap, ftJoin, ftMiterLimit);
363 PVG_FT_Stroker_ParseOutline(stroker, outline);
366 PVG_FT_UInt contours;
367 PVG_FT_Stroker_GetCounts(stroker, &points, &contours);
370 PVG_FT_Stroker_Export(stroker, stroke_outline);
372 PVG_FT_Stroker_Done(stroker);
374 return stroke_outline;
387 outline->flags = PVG_FT_OUTLINE_NONE;
391 outline->flags = PVG_FT_OUTLINE_EVEN_ODD_FILL;
394 outline->flags = PVG_FT_OUTLINE_NONE;
399 PVG_FT_Raster_Params params;
400 params.flags = PVG_FT_RASTER_FLAG_DIRECT | PVG_FT_RASTER_FLAG_AA;
402 params.user = span_buffer;
403 params.source = outline;
405 params.flags |= PVG_FT_RASTER_FLAG_CLIP;
406 params.clip_box.xMin = (PVG_FT_Pos)clip_rect->
x;
407 params.clip_box.yMin = (PVG_FT_Pos)clip_rect->
y;
408 params.clip_box.xMax = (PVG_FT_Pos)(clip_rect->
x + clip_rect->
w);
409 params.clip_box.yMax = (PVG_FT_Pos)(clip_rect->
y + clip_rect->
h);
413 PVG_FT_Raster_Render(¶ms);
#define NOVASVG_MAX(a, b)
#define NOVASVG_MIN(a, b)
void span_buffer_init_rect(span_buffer_t *span_buffer, int x, int y, int width, int height)
void span_buffer_init(span_buffer_t *span_buffer)
@ 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 path_iterator_init(path_iterator_t *it, const path_t *path)
Initializes a path iterator for a given path.
NOVASVG_INLINE void matrix_map_points(const matrix_t *matrix, const point_t *src, point_t *dst, int count)
Transforms an array of src points using matrix and stores the results in dst.
NOVASVG_INLINE PVG_FT_Outline * ft_outline_create(int points, int contours)
NOVASVG_INLINE void ft_outline_end(PVG_FT_Outline *ft)
NOVASVG_INLINE void ft_outline_cubic_to(PVG_FT_Outline *ft, float x1, float y1, float x2, float y2, float x3, float y3)
NOVASVG_INLINE void path_destroy(path_t *path)
Decreases the reference count of a path object.
NOVASVG_INLINE bool path_iterator_has_next(const path_iterator_t *it)
Checks if there are more elements to iterate over.
NOVASVG_INLINE void ft_outline_close(PVG_FT_Outline *ft)
NOVASVG_INLINE void span_buffer_update_extents(span_buffer_t *span_buffer)
@ NOVASVG_LINE_JOIN_BEVEL
Beveled join with a flattened corner.
@ NOVASVG_LINE_JOIN_ROUND
Rounded join.
fill_rule_t
Defines fill rule types for filling paths.
@ NOVASVG_FILL_RULE_EVEN_ODD
Even-odd fill rule.
NOVASVG_INLINE PVG_FT_Outline * ft_outline_convert_dash(const path_t *path, const matrix_t *matrix, const stroke_dash_t *stroke_dash)
NOVASVG_INLINE void spans_generation_callback(int count, const PVG_FT_Span *spans, void *user)
@ NOVASVG_LINE_CAP_SQUARE
Square ends at the end of the stroke.
@ NOVASVG_LINE_CAP_ROUND
Rounded ends at the end of the stroke.
void span_buffer_reset(span_buffer_t *span_buffer)
void span_buffer_destroy(span_buffer_t *span_buffer)
NOVASVG_INLINE void ft_outline_move_to(PVG_FT_Outline *ft, float x, float y)
void span_buffer_copy(span_buffer_t *span_buffer, const span_buffer_t *source)
void span_buffer_extents(span_buffer_t *span_buffer, rect_t *extents)
NOVASVG_INLINE path_t * path_clone_dashed(const path_t *path, float offset, const float *dashes, int ndashes)
Creates a copy of the path with a dashed pattern applied.
NOVASVG_INLINE void ft_outline_line_to(PVG_FT_Outline *ft, float x, float y)
NOVASVG_INLINE void ft_outline_destroy(PVG_FT_Outline *outline)
void span_buffer_intersect(span_buffer_t *span_buffer, const span_buffer_t *a, const span_buffer_t *b)
NOVASVG_INLINE path_command_t path_iterator_next(path_iterator_t *it, point_t points[3])
Retrieves the current command and its associated points, then advances the iterator.
NOVASVG_INLINE PVG_FT_Pos ft_coord_round(float v)
bool span_buffer_contains(const span_buffer_t *span_buffer, float x, float y)
NOVASVG_INLINE PVG_FT_Outline * ft_outline_convert(const path_t *path, const matrix_t *matrix, const stroke_data_t *stroke_data)
void rasterize(span_buffer_t *span_buffer, const path_t *path, const matrix_t *matrix, const rect_t *clip_rect, const stroke_data_t *stroke_data, fill_rule_t winding)
NOVASVG_INLINE PVG_FT_Outline * ft_outline_convert_stroke(const path_t *path, const matrix_t *matrix, const stroke_data_t *stroke_data)
Main namespace for the NovaSVG library.
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.
Iterator for traversing path elements in a path.
A structure representing a point in 2D space.
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.
struct novasvg::render::span_buffer_t::@12 spans
struct novasvg::render::stroke_dash_t::@13 array
#define novasvg_array_append_data(array, newdata, count)
#define novasvg_array_ensure(array, count)
#define novasvg_array_destroy(array)
#define novasvg_array_append(array, other)
#define novasvg_array_clear(array)
#define novasvg_array_init(array)