30#ifndef NANOSVGRAST_CPLUSPLUS
65 unsigned char* dst,
int w,
int h,
int stride);
71#ifndef NANOSVGRAST_CPLUSPLUS
77#ifdef NANOSVGRAST_IMPLEMENTATION
83#define NSVG__SUBSAMPLES 5
84#define NSVG__FIXSHIFT 10
85#define NSVG__FIX (1 << NSVG__FIXSHIFT)
86#define NSVG__FIXMASK (NSVG__FIX-1)
87#define NSVG__MEMPAGE_SIZE 1024
89typedef struct NSVGedge {
92 struct NSVGedge* next;
95typedef struct NSVGpoint {
103typedef struct NSVGactiveEdge {
107 struct NSVGactiveEdge *next;
110typedef struct NSVGmemPage {
111 unsigned char mem[NSVG__MEMPAGE_SIZE];
113 struct NSVGmemPage* next;
116typedef struct NSVGcachedPaint {
120 unsigned int colors[256];
142 NSVGactiveEdge* freelist;
144 NSVGmemPage* curpage;
146 unsigned char* scanline;
149 unsigned char* bitmap;
150 int width, height, stride;
156 if (r ==
NULL)
goto error;
173 if (r ==
NULL)
return;
177 NSVGmemPage* next = p->next;
182 if (r->edges)
free(r->edges);
183 if (r->points)
free(r->points);
184 if (r->points2)
free(r->points2);
185 if (r->scanline)
free(r->scanline);
190static NSVGmemPage* nsvg__nextPage(
NSVGrasterizer* r, NSVGmemPage* cur)
195 if (cur !=
NULL && cur->next !=
NULL) {
200 newp = (NSVGmemPage*)
malloc(
sizeof(NSVGmemPage));
202 memset(newp, 0,
sizeof(NSVGmemPage));
215 NSVGmemPage* p = r->pages;
220 r->curpage = r->pages;
226 if (
size > NSVG__MEMPAGE_SIZE)
return NULL;
227 if (r->curpage ==
NULL || r->curpage->size+
size > NSVG__MEMPAGE_SIZE) {
228 r->curpage = nsvg__nextPage(r, r->curpage);
230 buf = &r->curpage->mem[r->curpage->size];
231 r->curpage->size +=
size;
235static int nsvg__ptEquals(
float x1,
float y1,
float x2,
float y2,
float tol)
239 return dx*dx + dy*dy < tol*tol;
246 if (r->npoints > 0) {
247 pt = &r->points[r->npoints-1];
248 if (nsvg__ptEquals(
pt->
x,
pt->
y, x,y, r->distTol)) {
249 pt->flags = (
unsigned char)(
pt->flags |
flags);
254 if (r->npoints+1 > r->cpoints) {
255 r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
256 r->points = (NSVGpoint*)
realloc(r->points,
sizeof(NSVGpoint) * r->cpoints);
257 if (r->points ==
NULL)
return;
260 pt = &r->points[r->npoints];
263 pt->flags = (
unsigned char)
flags;
269 if (r->npoints+1 > r->cpoints) {
270 r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
271 r->points = (NSVGpoint*)
realloc(r->points,
sizeof(NSVGpoint) * r->cpoints);
272 if (r->points ==
NULL)
return;
274 r->points[r->npoints] =
pt;
280 if (r->npoints > r->cpoints2) {
281 r->cpoints2 = r->npoints;
282 r->points2 = (NSVGpoint*)
realloc(r->points2,
sizeof(NSVGpoint) * r->cpoints2);
283 if (r->points2 ==
NULL)
return;
286 memcpy(r->points2, r->points,
sizeof(NSVGpoint) * r->npoints);
287 r->npoints2 = r->npoints;
290static void nsvg__addEdge(
NSVGrasterizer* r,
float x0,
float y0,
float x1,
float y1)
298 if (r->nedges+1 > r->cedges) {
299 r->cedges = r->cedges > 0 ? r->cedges * 2 : 64;
300 r->edges = (NSVGedge*)
realloc(r->edges,
sizeof(NSVGedge) * r->cedges);
301 if (r->edges ==
NULL)
return;
304 e = &r->edges[r->nedges];
322static float nsvg__normalize(
float *x,
float* y)
324 float d =
sqrtf((*x)*(*x) + (*y)*(*y));
333static float nsvg__absf(
float x) {
return x < 0 ? -
x :
x; }
334static float nsvg__roundf(
float x) {
return (x >= 0) ?
floorf(x + 0.5) :
ceilf(
x - 0.5); }
337 float x1,
float y1,
float x2,
float y2,
338 float x3,
float y3,
float x4,
float y4,
341 float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234;
344 if (
level > 10)
return;
352 x123 = (x12+x23)*0.5f;
353 y123 = (y12+y23)*0.5f;
357 d2 = nsvg__absf((x2 - x4) * dy - (y2 - y4) * dx);
358 d3 = nsvg__absf((x3 - x4) * dy - (y3 - y4) * dx);
360 if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) {
361 nsvg__addPathPoint(r, x4, y4, type);
365 x234 = (x23+x34)*0.5f;
366 y234 = (y23+y34)*0.5f;
367 x1234 = (x123+x234)*0.5f;
368 y1234 = (y123+y234)*0.5f;
370 nsvg__flattenCubicBez(r, x1,y1, x12,y12, x123,y123, x1234,y1234,
level+1, 0);
371 nsvg__flattenCubicBez(r, x1234,y1234, x234,y234, x34,y34, x4,y4,
level+1, type);
382 nsvg__addPathPoint(r,
path->pts[0]*scale,
path->pts[1]*scale, 0);
383 for (i = 0; i <
path->npts-1; i += 3) {
384 float* p = &
path->pts[i*2];
385 nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, 0);
388 nsvg__addPathPoint(r,
path->pts[0]*scale,
path->pts[1]*scale, 0);
390 for (i = 0, j = r->npoints-1; i < r->npoints; j = i++)
391 nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y);
397 NSVG_PT_CORNER = 0x01,
398 NSVG_PT_BEVEL = 0x02,
402static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1,
float lineWidth)
404 float w = lineWidth * 0.5f;
405 float dx = p1->x - p0->x;
406 float dy = p1->y - p0->y;
407 float len = nsvg__normalize(&dx, &dy);
408 float px = p0->x + dx*
len*0.5f, py = p0->y + dy*
len*0.5f;
409 float dlx = dy, dly = -dx;
410 float lx = px - dlx*
w, ly = py - dly*
w;
411 float rx = px + dlx*
w, ry = py + dly*
w;
412 left->x = lx; left->y = ly;
413 right->x = rx; right->y = ry;
416static void nsvg__buttCap(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p,
float dx,
float dy,
float lineWidth,
int connect)
418 float w = lineWidth * 0.5f;
419 float px = p->x, py = p->y;
420 float dlx = dy, dly = -dx;
421 float lx = px - dlx*
w, ly = py - dly*
w;
422 float rx = px + dlx*
w, ry = py + dly*
w;
424 nsvg__addEdge(r, lx, ly, rx, ry);
427 nsvg__addEdge(r, left->x, left->y, lx, ly);
428 nsvg__addEdge(r, rx, ry, right->x, right->y);
430 left->x = lx; left->y = ly;
431 right->x = rx; right->y = ry;
434static void nsvg__squareCap(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p,
float dx,
float dy,
float lineWidth,
int connect)
436 float w = lineWidth * 0.5f;
437 float px = p->x - dx*
w, py = p->y - dy*
w;
438 float dlx = dy, dly = -dx;
439 float lx = px - dlx*
w, ly = py - dly*
w;
440 float rx = px + dlx*
w, ry = py + dly*
w;
442 nsvg__addEdge(r, lx, ly, rx, ry);
445 nsvg__addEdge(r, left->x, left->y, lx, ly);
446 nsvg__addEdge(r, rx, ry, right->x, right->y);
448 left->x = lx; left->y = ly;
449 right->x = rx; right->y = ry;
453#define NSVG_PI (3.14159265358979323846264338327f)
456static void nsvg__roundCap(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p,
float dx,
float dy,
float lineWidth,
int ncap,
int connect)
459 float w = lineWidth * 0.5f;
460 float px = p->x, py = p->y;
461 float dlx = dy, dly = -dx;
462 float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0;
464 for (i = 0; i < ncap; i++) {
465 float a = (float)i/(
float)(ncap-1)*NSVG_PI;
467 float x = px - dlx*ax - dx*ay;
468 float y = py - dly*ax - dy*ay;
471 nsvg__addEdge(r, prevx, prevy, x, y);
478 }
else if (i == ncap-1) {
484 nsvg__addEdge(r, left->x, left->y, lx, ly);
485 nsvg__addEdge(r, rx, ry, right->x, right->y);
488 left->x = lx; left->y = ly;
489 right->x = rx; right->y = ry;
492static void nsvg__bevelJoin(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1,
float lineWidth)
494 float w = lineWidth * 0.5f;
495 float dlx0 = p0->dy, dly0 = -p0->dx;
496 float dlx1 = p1->dy, dly1 = -p1->dx;
497 float lx0 = p1->x - (dlx0 *
w), ly0 = p1->y - (dly0 * w);
498 float rx0 = p1->x + (dlx0 *
w), ry0 = p1->y + (dly0 * w);
499 float lx1 = p1->x - (dlx1 *
w), ly1 = p1->y - (dly1 * w);
500 float rx1 = p1->x + (dlx1 *
w), ry1 = p1->y + (dly1 * w);
502 nsvg__addEdge(r, lx0, ly0, left->x, left->y);
503 nsvg__addEdge(r, lx1, ly1, lx0, ly0);
505 nsvg__addEdge(r, right->x, right->y, rx0, ry0);
506 nsvg__addEdge(r, rx0, ry0, rx1, ry1);
508 left->x = lx1; left->y = ly1;
509 right->x = rx1; right->y = ry1;
512static void nsvg__miterJoin(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1,
float lineWidth)
514 float w = lineWidth * 0.5f;
515 float dlx0 = p0->dy, dly0 = -p0->dx;
516 float dlx1 = p1->dy, dly1 = -p1->dx;
517 float lx0, rx0, lx1, rx1;
518 float ly0, ry0, ly1, ry1;
520 if (p1->flags & NSVG_PT_LEFT) {
521 lx0 = lx1 = p1->x - p1->dmx *
w;
522 ly0 = ly1 = p1->y - p1->dmy *
w;
523 nsvg__addEdge(r, lx1, ly1, left->x, left->y);
525 rx0 = p1->x + (dlx0 *
w);
526 ry0 = p1->y + (dly0 *
w);
527 rx1 = p1->x + (dlx1 *
w);
528 ry1 = p1->y + (dly1 *
w);
529 nsvg__addEdge(r, right->x, right->y, rx0, ry0);
530 nsvg__addEdge(r, rx0, ry0, rx1, ry1);
532 lx0 = p1->x - (dlx0 *
w);
533 ly0 = p1->y - (dly0 *
w);
534 lx1 = p1->x - (dlx1 *
w);
535 ly1 = p1->y - (dly1 *
w);
536 nsvg__addEdge(r, lx0, ly0, left->x, left->y);
537 nsvg__addEdge(r, lx1, ly1, lx0, ly0);
539 rx0 = rx1 = p1->x + p1->dmx *
w;
540 ry0 = ry1 = p1->y + p1->dmy *
w;
541 nsvg__addEdge(r, right->x, right->y, rx1, ry1);
544 left->x = lx1; left->y = ly1;
545 right->x = rx1; right->y = ry1;
548static void nsvg__roundJoin(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1,
float lineWidth,
int ncap)
551 float w = lineWidth * 0.5f;
552 float dlx0 = p0->dy, dly0 = -p0->dx;
553 float dlx1 = p1->dy, dly1 = -p1->dx;
554 float a0 =
atan2f(dly0, dlx0);
555 float a1 =
atan2f(dly1, dlx1);
557 float lx, ly, rx, ry;
559 if (da < NSVG_PI) da += NSVG_PI*2;
560 if (da > NSVG_PI) da -= NSVG_PI*2;
562 n = (int)
ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap);
564 if (n > ncap) n = ncap;
571 for (i = 0; i < n; i++) {
572 float u = (float)i/(
float)(n-1);
575 float lx1 = p1->x - ax, ly1 = p1->y - ay;
576 float rx1 = p1->x + ax, ry1 = p1->y + ay;
578 nsvg__addEdge(r, lx1, ly1, lx, ly);
579 nsvg__addEdge(r, rx, ry, rx1, ry1);
585 left->x = lx; left->y = ly;
586 right->x = rx; right->y = ry;
589static void nsvg__straightJoin(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1,
float lineWidth)
591 float w = lineWidth * 0.5f;
592 float lx = p1->x - (p1->dmx *
w), ly = p1->y - (p1->dmy * w);
593 float rx = p1->x + (p1->dmx *
w), ry = p1->y + (p1->dmy * w);
595 nsvg__addEdge(r, lx, ly, left->x, left->y);
596 nsvg__addEdge(r, right->x, right->y, rx, ry);
598 left->x = lx; left->y = ly;
599 right->x = rx; right->y = ry;
602static int nsvg__curveDivs(
float r,
float arc,
float tol)
604 float da =
acosf(r / (r + tol)) * 2.0f;
605 int divs = (int)
ceilf(arc / da);
606 if (divs < 2) divs = 2;
610static void nsvg__expandStroke(
NSVGrasterizer* r, NSVGpoint* points,
int npoints,
int closed,
int lineJoin,
int lineCap,
float lineWidth)
612 int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol);
613 NSVGpoint left = {0,0,0,0,0,0,0,0}, right = {0,0,0,0,0,0,0,0}, firstLeft = {0,0,0,0,0,0,0,0}, firstRight = {0,0,0,0,0,0,0,0};
620 p0 = &points[npoints-1];
633 nsvg__initClosed(&left, &right, p0, p1, lineWidth);
638 float dx = p1->x - p0->x;
639 float dy = p1->y - p0->y;
640 nsvg__normalize(&dx, &dy);
642 nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
644 nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
646 nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0);
649 for (j = s; j < e; ++j) {
650 if (p1->flags & NSVG_PT_CORNER) {
652 nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap);
654 nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth);
656 nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth);
658 nsvg__straightJoin(r, &left, &right, p1, lineWidth);
665 nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y);
666 nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y);
669 float dx = p1->x - p0->x;
670 float dy = p1->y - p0->y;
671 nsvg__normalize(&dx, &dy);
673 nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
675 nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
677 nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1);
681static void nsvg__prepareStroke(
NSVGrasterizer* r,
float miterLimit,
int lineJoin)
686 p0 = &r->points[r->npoints-1];
688 for (i = 0; i < r->npoints; i++) {
690 p0->dx = p1->x - p0->x;
691 p0->dy = p1->y - p0->y;
692 p0->len = nsvg__normalize(&p0->dx, &p0->dy);
698 p0 = &r->points[r->npoints-1];
700 for (j = 0; j < r->npoints; j++) {
701 float dlx0, dly0, dlx1, dly1, dmr2, cross;
707 p1->dmx = (dlx0 + dlx1) * 0.5f;
708 p1->dmy = (dly0 + dly1) * 0.5f;
709 dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy;
710 if (dmr2 > 0.000001f) {
711 float s2 = 1.0f / dmr2;
720 p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0;
723 cross = p1->dx * p0->dy - p0->dx * p1->dy;
725 p1->flags |= NSVG_PT_LEFT;
728 if (p1->flags & NSVG_PT_CORNER) {
730 p1->flags |= NSVG_PT_BEVEL;
743 float miterLimit =
shape->miterLimit;
744 int lineJoin =
shape->strokeLineJoin;
745 int lineCap =
shape->strokeLineCap;
746 float lineWidth =
shape->strokeWidth * scale;
751 nsvg__addPathPoint(r,
path->pts[0]*scale,
path->pts[1]*scale, NSVG_PT_CORNER);
752 for (i = 0; i <
path->npts-1; i += 3) {
753 float* p = &
path->pts[i*2];
754 nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, NSVG_PT_CORNER);
759 closed =
path->closed;
762 p0 = &r->points[r->npoints-1];
764 if (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) {
766 p0 = &r->points[r->npoints-1];
770 if (
shape->strokeDashCount > 0) {
771 int idash = 0, dashState = 1;
772 float totalDist = 0, dashLen, allDashLen, dashOffset;
776 nsvg__appendPathPoint(r, r->points[0]);
779 nsvg__duplicatePoints(r);
783 nsvg__appendPathPoint(r, cur);
787 for (j = 0; j <
shape->strokeDashCount; j++)
788 allDashLen +=
shape->strokeDashArray[j];
789 if (
shape->strokeDashCount & 1)
792 dashOffset =
fmodf(
shape->strokeDashOffset, allDashLen);
793 if (dashOffset < 0.0f)
794 dashOffset += allDashLen;
796 while (dashOffset >
shape->strokeDashArray[idash]) {
797 dashOffset -=
shape->strokeDashArray[idash];
798 idash = (idash + 1) %
shape->strokeDashCount;
800 dashLen = (
shape->strokeDashArray[idash] - dashOffset) * scale;
802 for (j = 1; j < r->npoints2; ) {
803 float dx = r->points2[j].x - cur.x;
804 float dy = r->points2[j].y - cur.y;
805 float dist =
sqrtf(dx*dx + dy*dy);
807 if ((totalDist + dist) > dashLen) {
809 float d = (dashLen - totalDist) / dist;
810 float x = cur.x + dx *
d;
811 float y = cur.y + dy *
d;
812 nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER);
815 if (r->npoints > 1 && dashState) {
816 nsvg__prepareStroke(r, miterLimit, lineJoin);
817 nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
820 dashState = !dashState;
821 idash = (idash+1) %
shape->strokeDashCount;
822 dashLen =
shape->strokeDashArray[idash] * scale;
826 cur.flags = NSVG_PT_CORNER;
829 nsvg__appendPathPoint(r, cur);
833 nsvg__appendPathPoint(r, cur);
838 if (r->npoints > 1 && dashState) {
839 nsvg__prepareStroke(r, miterLimit, lineJoin);
840 nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
843 nsvg__prepareStroke(r, miterLimit, lineJoin);
844 nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth);
849static int nsvg__cmpEdge(
const void *p,
const void *q)
851 const NSVGedge*
a = (
const NSVGedge*)p;
852 const NSVGedge*
b = (
const NSVGedge*)q;
854 if (
a->y0 <
b->y0)
return -1;
855 if (
a->y0 >
b->y0)
return 1;
860static NSVGactiveEdge* nsvg__addActive(
NSVGrasterizer* r, NSVGedge* e,
float startPoint)
864 if (r->freelist !=
NULL) {
867 r->freelist = z->next;
870 z = (NSVGactiveEdge*)nsvg__alloc(r,
sizeof(NSVGactiveEdge));
874 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
878 z->dx = (int)(-nsvg__roundf(NSVG__FIX * -dxdy));
880 z->dx = (int)nsvg__roundf(NSVG__FIX * dxdy);
881 z->x = (int)nsvg__roundf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));
892 z->next = r->freelist;
896static void nsvg__fillScanline(
unsigned char* scanline,
int len,
int x0,
int x1,
int maxWeight,
int* xmin,
int* xmax)
898 int i = x0 >> NSVG__FIXSHIFT;
899 int j = x1 >> NSVG__FIXSHIFT;
900 if (i < *xmin) *xmin = i;
901 if (j > *xmax) *xmax = j;
902 if (i < len && j >= 0) {
905 scanline[i] = (
unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT));
908 scanline[i] = (
unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT));
913 scanline[j] = (
unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT));
917 for (++i; i < j; ++i)
918 scanline[i] = (
unsigned char)(scanline[i] + maxWeight);
926static void nsvg__fillActiveEdges(
unsigned char* scanline,
int len, NSVGactiveEdge* e,
int maxWeight,
int* xmin,
int* xmax,
char fillRule)
936 x0 = e->x;
w += e->dir;
938 int x1 = e->x;
w += e->dir;
941 nsvg__fillScanline(scanline,
len, x0, x1, maxWeight, xmin, xmax);
952 int x1 = e->x;
w = 0;
953 nsvg__fillScanline(scanline,
len, x0, x1, maxWeight, xmin, xmax);
960static float nsvg__clampf(
float a,
float mn,
float mx) {
963 return a < mn ? mn : (
a > mx ? mx :
a);
966static unsigned int nsvg__RGBA(
unsigned char r,
unsigned char g,
unsigned char b,
unsigned char a)
968 return ((
unsigned int)r) | ((
unsigned int)g << 8) | ((
unsigned int)
b << 16) | ((
unsigned int)
a << 24);
971static unsigned int nsvg__lerpRGBA(
unsigned int c0,
unsigned int c1,
float u)
973 int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
974 int r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8;
975 int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8;
976 int b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8;
977 int a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8;
978 return nsvg__RGBA((
unsigned char)r, (
unsigned char)g, (
unsigned char)
b, (
unsigned char)
a);
981static unsigned int nsvg__applyOpacity(
unsigned int c,
float u)
983 int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
985 int g = (c>>8) & 0xff;
986 int b = (c>>16) & 0xff;
987 int a = (((c>>24) & 0xff)*iu) >> 8;
988 return nsvg__RGBA((
unsigned char)r, (
unsigned char)g, (
unsigned char)
b, (
unsigned char)
a);
991static inline int nsvg__div255(
int x)
993 return ((x+1) * 257) >> 16;
996static void nsvg__scanlineSolid(
unsigned char* dst,
int count,
unsigned char* cover,
int x,
int y,
997 float tx,
float ty,
float scale, NSVGcachedPaint* cache)
1001 int i, cr, cg, cb, ca;
1002 cr = cache->colors[0] & 0xff;
1003 cg = (cache->colors[0] >> 8) & 0xff;
1004 cb = (cache->colors[0] >> 16) & 0xff;
1005 ca = (cache->colors[0] >> 24) & 0xff;
1007 for (i = 0; i < count; i++) {
1009 int a = nsvg__div255((
int)cover[0] * ca);
1012 r = nsvg__div255(cr *
a);
1013 g = nsvg__div255(cg *
a);
1014 b = nsvg__div255(cb *
a);
1017 r += nsvg__div255(ia * (
int)dst[0]);
1018 g += nsvg__div255(ia * (
int)dst[1]);
1019 b += nsvg__div255(ia * (
int)dst[2]);
1020 a += nsvg__div255(ia * (
int)dst[3]);
1022 dst[0] = (
unsigned char)r;
1023 dst[1] = (
unsigned char)g;
1024 dst[2] = (
unsigned char)
b;
1025 dst[3] = (
unsigned char)
a;
1033 float fx, fy, dx, gy;
1034 float*
t = cache->xform;
1035 int i, cr, cg, cb, ca;
1038 fx = ((float)x - tx) / scale;
1039 fy = ((float)y - ty) / scale;
1042 for (i = 0; i < count; i++) {
1044 gy = fx*
t[1] + fy*
t[3] +
t[5];
1045 c = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)];
1047 cg = (c >> 8) & 0xff;
1048 cb = (c >> 16) & 0xff;
1049 ca = (c >> 24) & 0xff;
1051 a = nsvg__div255((
int)cover[0] * ca);
1055 r = nsvg__div255(cr *
a);
1056 g = nsvg__div255(cg *
a);
1057 b = nsvg__div255(cb *
a);
1060 r += nsvg__div255(ia * (
int)dst[0]);
1061 g += nsvg__div255(ia * (
int)dst[1]);
1062 b += nsvg__div255(ia * (
int)dst[2]);
1063 a += nsvg__div255(ia * (
int)dst[3]);
1065 dst[0] = (
unsigned char)r;
1066 dst[1] = (
unsigned char)g;
1067 dst[2] = (
unsigned char)
b;
1068 dst[3] = (
unsigned char)
a;
1078 float fx, fy, dx, gx, gy, gd;
1079 float*
t = cache->xform;
1080 int i, cr, cg, cb, ca;
1083 fx = ((float)x - tx) / scale;
1084 fy = ((float)y - ty) / scale;
1087 for (i = 0; i < count; i++) {
1089 gx = fx*
t[0] + fy*
t[2] +
t[4];
1090 gy = fx*
t[1] + fy*
t[3] +
t[5];
1091 gd =
sqrtf(gx*gx + gy*gy);
1092 c = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)];
1094 cg = (c >> 8) & 0xff;
1095 cb = (c >> 16) & 0xff;
1096 ca = (c >> 24) & 0xff;
1098 a = nsvg__div255((
int)cover[0] * ca);
1102 r = nsvg__div255(cr *
a);
1103 g = nsvg__div255(cg *
a);
1104 b = nsvg__div255(cb *
a);
1107 r += nsvg__div255(ia * (
int)dst[0]);
1108 g += nsvg__div255(ia * (
int)dst[1]);
1109 b += nsvg__div255(ia * (
int)dst[2]);
1110 a += nsvg__div255(ia * (
int)dst[3]);
1112 dst[0] = (
unsigned char)r;
1113 dst[1] = (
unsigned char)g;
1114 dst[2] = (
unsigned char)
b;
1115 dst[3] = (
unsigned char)
a;
1124static void nsvg__rasterizeSortedEdges(
NSVGrasterizer *r,
float tx,
float ty,
float scale, NSVGcachedPaint* cache,
char fillRule)
1126 NSVGactiveEdge *active =
NULL;
1129 int maxWeight = (255 / NSVG__SUBSAMPLES);
1132 for (y = 0;
y < r->height;
y++) {
1133 memset(r->scanline, 0, r->width);
1136 for (s = 0; s < NSVG__SUBSAMPLES; ++s) {
1138 float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f;
1139 NSVGactiveEdge **step = &active;
1144 NSVGactiveEdge *z = *step;
1145 if (z->ey <= scany) {
1148 nsvg__freeActive(r, z);
1151 step = &((*step)->next);
1159 while (*step && (*step)->next) {
1160 if ((*step)->x > (*step)->next->x) {
1161 NSVGactiveEdge*
t = *step;
1162 NSVGactiveEdge* q =
t->next;
1168 step = &(*step)->next;
1170 if (!changed)
break;
1174 while (e < r->nedges && r->edges[e].y0 <= scany) {
1175 if (r->edges[e].y1 > scany) {
1176 NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany);
1177 if (z ==
NULL)
break;
1179 if (active ==
NULL) {
1181 }
else if (z->x < active->x) {
1187 NSVGactiveEdge* p = active;
1188 while (p->next && p->next->x < z->x)
1200 nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule);
1203 if (xmin < 0) xmin = 0;
1204 if (xmax > r->width-1) xmax = r->width-1;
1206 nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scale, cache);
1212static void nsvg__unpremultiplyAlpha(
unsigned char*
image,
int w,
int h,
int stride)
1217 for (y = 0;
y <
h;
y++) {
1218 unsigned char *row = &
image[
y*stride];
1219 for (x = 0;
x <
w;
x++) {
1220 int r = row[0], g = row[1],
b = row[2],
a = row[3];
1222 row[0] = (
unsigned char)(r*255/
a);
1223 row[1] = (
unsigned char)(g*255/
a);
1224 row[2] = (
unsigned char)(
b*255/
a);
1231 for (y = 0;
y <
h;
y++) {
1232 unsigned char *row = &
image[
y*stride];
1233 for (x = 0;
x <
w;
x++) {
1234 int r = 0, g = 0,
b = 0,
a = row[3], n = 0;
1236 if (x-1 > 0 && row[-1] != 0) {
1242 if (x+1 < w && row[7] != 0) {
1248 if (y-1 > 0 && row[-stride+3] != 0) {
1250 g += row[-stride+1];
1251 b += row[-stride+2];
1254 if (y+1 <
h && row[stride+3] != 0) {
1261 row[0] = (
unsigned char)(r/n);
1262 row[1] = (
unsigned char)(g/n);
1263 row[2] = (
unsigned char)(
b/n);
1272static void nsvg__initPaint(NSVGcachedPaint* cache,
NSVGpaint* paint,
float opacity)
1277 cache->type = paint->
type;
1280 cache->colors[0] = nsvg__applyOpacity(paint->
color, opacity);
1286 cache->spread = grad->
spread;
1287 memcpy(cache->xform, grad->
xform,
sizeof(
float)*6);
1290 for (i = 0; i < 256; i++)
1291 cache->colors[i] = 0;
1292 }
else if (grad->
nstops == 1) {
1293 unsigned int color = nsvg__applyOpacity(grad->
stops[0].
color, opacity);
1294 for (i = 0; i < 256; i++)
1295 cache->colors[i] =
color;
1297 unsigned int ca, cb = 0;
1298 float ua, ub, du, u;
1301 ca = nsvg__applyOpacity(grad->
stops[0].
color, opacity);
1304 ia = (int)(ua * 255.0f);
1305 ib = (int)(ub * 255.0f);
1306 for (i = 0; i < ia; i++) {
1307 cache->colors[i] = ca;
1310 for (i = 0; i < grad->
nstops-1; i++) {
1311 ca = nsvg__applyOpacity(grad->
stops[i].
color, opacity);
1312 cb = nsvg__applyOpacity(grad->
stops[i+1].
color, opacity);
1315 ia = (int)(ua * 255.0f);
1316 ib = (int)(ub * 255.0f);
1318 if (count <= 0)
continue;
1320 du = 1.0f / (float)count;
1321 for (j = 0; j < count; j++) {
1322 cache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u);
1327 for (i = ib; i < 256; i++)
1328 cache->colors[i] = cb;
1377 unsigned char* dst,
int w,
int h,
int stride)
1381 NSVGcachedPaint cache;
1384 unsigned char paintOrder;
1391 if (w > r->cscanline) {
1393 r->scanline = (
unsigned char*)
realloc(r->scanline, w);
1394 if (r->scanline ==
NULL)
return;
1397 for (i = 0; i <
h; i++)
1398 memset(&dst[i*stride], 0, w*4);
1404 for (j = 0; j < 3; j++) {
1405 paintOrder = (
shape->paintOrder >> (2 * j)) & 0x03;
1412 nsvg__flattenShape(r,
shape, scale);
1415 for (i = 0; i < r->nedges; i++) {
1418 e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
1420 e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
1425 qsort(r->edges, r->nedges,
sizeof(NSVGedge), nsvg__cmpEdge);
1428 nsvg__initPaint(&cache, &
shape->fill,
shape->opacity);
1430 nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache,
shape->fillRule);
1437 nsvg__flattenShapeStroke(r,
shape, scale);
1442 for (i = 0; i < r->nedges; i++) {
1445 e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
1447 e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
1452 qsort(r->edges, r->nedges,
sizeof(NSVGedge), nsvg__cmpEdge);
1455 nsvg__initPaint(&cache, &
shape->stroke,
shape->opacity);
1462 nsvg__unpremultiplyAlpha(dst, w,
h, stride);
uint8_t flags
Definition virtio.h:0
@ NSVG_FILLRULE_NONZERO
Definition nanosvg.h:101
@ NSVG_FILLRULE_EVENODD
Definition nanosvg.h:102
@ NSVG_PAINT_STROKE
Definition nanosvg.h:112
@ NSVG_PAINT_FILL
Definition nanosvg.h:110
@ NSVG_CAP_SQUARE
Definition nanosvg.h:97
@ NSVG_CAP_BUTT
Definition nanosvg.h:95
@ NSVG_CAP_ROUND
Definition nanosvg.h:96
@ NSVG_FLAGS_VISIBLE
Definition nanosvg.h:106
@ NSVG_PAINT_NONE
Definition nanosvg.h:76
@ NSVG_PAINT_COLOR
Definition nanosvg.h:77
@ NSVG_PAINT_RADIAL_GRADIENT
Definition nanosvg.h:79
@ NSVG_PAINT_LINEAR_GRADIENT
Definition nanosvg.h:78
@ NSVG_JOIN_BEVEL
Definition nanosvg.h:91
@ NSVG_JOIN_ROUND
Definition nanosvg.h:90
NSVGrasterizer * nsvgCreateRasterizer(void)
void nsvgRasterize(NSVGrasterizer *r, NSVGimage *image, float tx, float ty, float scale, unsigned char *dst, int w, int h, int stride)
void nsvgDeleteRasterizer(NSVGrasterizer *)
struct NSVGrasterizer NSVGrasterizer
Definition nanosvgrast.h:36
#define isnan(x)
Definition math.h:150
XE_LIB float floorf(float)
Definition math.cpp:145
XE_LIB float sqrtf(float x)
Definition math.cpp:293
XE_LIB float sinf(float)
Definition math.cpp:222
XE_LIB float cosf(float)
Definition math.cpp:94
XE_LIB int connect(int sockfd, sockaddr_ *addr, socklen_t addrlen)
XETime t
Definition main.cpp:53
size_t a
Definition main.cpp:156
size_t b
Definition main.cpp:156
float acosf(float x)
Definition acosf.cpp:45
#define NULL
Definition actypes.h:561
float atan2f(float y, float x)
Definition atan2f.cpp:35
size_t pages
Definition audrv.c:83
shape
Definition bytecode.h:83
float ceilf(float x)
Definition ceilf.cpp:3
size_t size
Definition drm_bridge.h:1299
const char * level
Definition drm_print.h:515
float fmodf(float x, float y)
Definition fmodf.cpp:10
__u64 image
Definition i915_drm.h:14
size_t len
Definition initial.c:23
int y
Definition layout.c:118
int h
Definition layout.c:118
int x
Definition layout.c:118
int w
Definition layout.c:118
#define d
Definition libunicode.c:1833
#define realloc(p, s)
Definition quickjs.c:2292
#define malloc(s)
Definition quickjs.c:2290
#define free(p)
Definition quickjs.c:2291
XE_LIB void qsort(void *base, size_t num, size_t size, int(*comparator)(const void *, const void *))
Definition qsort.cpp:78
unsigned int color
Definition nanosvg.h:116
float offset
Definition nanosvg.h:117
float xform[6]
Definition nanosvg.h:121
NSVGgradientStop stops[1]
Definition nanosvg.h:125
int nstops
Definition nanosvg.h:124
char spread
Definition nanosvg.h:122
unsigned int color
Definition nanosvg.h:131
NSVGgradient * gradient
Definition nanosvg.h:132
signed char type
Definition nanosvg.h:129
fe x
Definition crypto.c:515
fe y
Definition crypto.c:515