ES-DE/external/lunasvg/3rdparty/plutovg/plutovg-dash.c

115 lines
2.9 KiB
C

#include "plutovg-private.h"
#include <math.h>
plutovg_dash_t* plutovg_dash_create(double offset, const double* data, int size)
{
if(data==NULL || size==0)
return NULL;
plutovg_dash_t* dash = malloc(sizeof(plutovg_dash_t));
dash->offset = offset;
dash->data = malloc((size_t)size * sizeof(double));
dash->size = size;
memcpy(dash->data, data, (size_t)size * sizeof(double));
return dash;
}
plutovg_dash_t* plutovg_dash_clone(const plutovg_dash_t* dash)
{
if(dash==NULL)
return NULL;
return plutovg_dash_create(dash->offset, dash->data, dash->size);
}
void plutovg_dash_destroy(plutovg_dash_t* dash)
{
if(dash==NULL)
return;
free(dash->data);
free(dash);
}
plutovg_path_t* plutovg_dash_path(const plutovg_dash_t* dash, const plutovg_path_t* path)
{
if(dash->data==NULL || dash->size==0)
return plutovg_path_clone(path);
int toggle = 1;
int offset = 0;
double phase = dash->offset;
while(phase >= dash->data[offset])
{
toggle = !toggle;
phase -= dash->data[offset];
offset += 1;
if(offset == dash->size) offset = 0;
}
plutovg_path_t* flat = plutovg_path_clone_flat(path);
plutovg_path_t* result = plutovg_path_create();
plutovg_array_ensure(result->elements, flat->elements.size);
plutovg_array_ensure(result->points, flat->points.size);
plutovg_path_element_t* elements = flat->elements.data;
plutovg_path_element_t* end = elements + flat->elements.size;
plutovg_point_t* points = flat->points.data;
while(elements < end)
{
int itoggle = toggle;
int ioffset = offset;
double iphase = phase;
double x0 = points->x;
double y0 = points->y;
if(itoggle)
plutovg_path_move_to(result, x0, y0);
++elements;
++points;
while(elements < end && *elements==plutovg_path_element_line_to)
{
double dx = points->x - x0;
double dy = points->y - y0;
double dist0 = sqrt(dx*dx + dy*dy);
double dist1 = 0;
while(dist0 - dist1 > dash->data[ioffset] - iphase)
{
dist1 += dash->data[ioffset] - iphase;
double a = dist1 / dist0;
double x = x0 + a * dx;
double y = y0 + a * dy;
if(itoggle)
plutovg_path_line_to(result, x, y);
else
plutovg_path_move_to(result, x, y);
itoggle = !itoggle;
iphase = 0;
ioffset += 1;
if(ioffset == dash->size) ioffset = 0;
}
iphase += dist0 - dist1;
x0 = points->x;
y0 = points->y;
if(itoggle)
plutovg_path_line_to(result, x0, y0);
++elements;
++points;
}
}
plutovg_path_destroy(flat);
return result;
}