30#ifndef NANOSVGRAST_CPLUSPLUS
64 NSVGimage* image,
float tx,
float ty,
float scale,
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;
242static void nsvg__addPathPoint(
NSVGrasterizer* r,
float x,
float y,
int flags)
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];
323static float nsvg__normalize(
float* x,
float* y)
325 float d =
sqrtf((*x) * (*x) + (*y) * (*y));
334static float nsvg__absf(
float x) {
return x < 0 ? -
x :
x; }
335static float nsvg__roundf(
float x) {
return (x >= 0) ?
floorf(x + 0.5) :
ceilf(
x - 0.5); }
338 float x1,
float y1,
float x2,
float y2,
339 float x3,
float y3,
float x4,
float y4,
342 float x12, y12, x23, y23, x34, y34, x123, y123, x234, y234, x1234, y1234;
343 float dx, dy, d2, d3;
345 if (level > 10)
return;
347 x12 = (x1 + x2) * 0.5f;
348 y12 = (y1 + y2) * 0.5f;
349 x23 = (x2 + x3) * 0.5f;
350 y23 = (y2 + y3) * 0.5f;
351 x34 = (x3 + x4) * 0.5f;
352 y34 = (y3 + y4) * 0.5f;
353 x123 = (x12 + x23) * 0.5f;
354 y123 = (y12 + y23) * 0.5f;
358 d2 = nsvg__absf((x2 - x4) * dy - (y2 - y4) * dx);
359 d3 = nsvg__absf((x3 - x4) * dy - (y3 - y4) * dx);
361 if ((d2 + d3) * (d2 + d3) < r->tessTol * (dx * dx + dy * dy)) {
362 nsvg__addPathPoint(r, x4, y4, type);
366 x234 = (x23 + x34) * 0.5f;
367 y234 = (y23 + y34) * 0.5f;
368 x1234 = (x123 + x234) * 0.5f;
369 y1234 = (y123 + y234) * 0.5f;
371 nsvg__flattenCubicBez(r, x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1, 0);
372 nsvg__flattenCubicBez(r, x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1, type);
383 nsvg__addPathPoint(r,
path->pts[0] * scale,
path->pts[1] * scale, 0);
384 for (i = 0; i <
path->npts - 1; i += 3) {
385 float* p = &
path->pts[i * 2];
386 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);
389 nsvg__addPathPoint(r,
path->pts[0] * scale,
path->pts[1] * scale, 0);
391 for (i = 0, j = r->npoints - 1; i < r->npoints; j = i++)
392 nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y);
398 NSVG_PT_CORNER = 0x01,
399 NSVG_PT_BEVEL = 0x02,
403static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1,
float lineWidth)
405 float w = lineWidth * 0.5f;
406 float dx = p1->x - p0->x;
407 float dy = p1->y - p0->y;
408 float len = nsvg__normalize(&dx, &dy);
409 float px = p0->x + dx * len * 0.5f, py = p0->y + dy * len * 0.5f;
410 float dlx = dy, dly = -dx;
411 float lx = px - dlx * w, ly = py - dly * w;
412 float rx = px + dlx * w, ry = py + dly * w;
413 left->x = lx; left->y = ly;
414 right->x = rx; right->y = ry;
417static void nsvg__buttCap(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p,
float dx,
float dy,
float lineWidth,
int connect)
419 float w = lineWidth * 0.5f;
420 float px = p->x, py = p->y;
421 float dlx = dy, dly = -dx;
422 float lx = px - dlx * w, ly = py - dly * w;
423 float rx = px + dlx * w, ry = py + dly * w;
425 nsvg__addEdge(r, lx, ly, rx, ry);
428 nsvg__addEdge(r, left->x, left->y, lx, ly);
429 nsvg__addEdge(r, rx, ry, right->x, right->y);
431 left->x = lx; left->y = ly;
432 right->x = rx; right->y = ry;
435static void nsvg__squareCap(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p,
float dx,
float dy,
float lineWidth,
int connect)
437 float w = lineWidth * 0.5f;
438 float px = p->x - dx * w, py = p->y - dy * w;
439 float dlx = dy, dly = -dx;
440 float lx = px - dlx * w, ly = py - dly * w;
441 float rx = px + dlx * w, ry = py + dly * w;
443 nsvg__addEdge(r, lx, ly, rx, ry);
446 nsvg__addEdge(r, left->x, left->y, lx, ly);
447 nsvg__addEdge(r, rx, ry, right->x, right->y);
449 left->x = lx; left->y = ly;
450 right->x = rx; right->y = ry;
454#define NSVG_PI (3.14159265358979323846264338327f)
457static void nsvg__roundCap(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p,
float dx,
float dy,
float lineWidth,
int ncap,
int connect)
460 float w = lineWidth * 0.5f;
461 float px = p->x, py = p->y;
462 float dlx = dy, dly = -dx;
463 float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0;
465 for (i = 0; i < ncap; i++) {
466 float a = (float)i / (
float)(ncap - 1) * NSVG_PI;
467 float ax =
cosf(a) * w, ay =
sinf(a) * w;
468 float x = px - dlx * ax - dx * ay;
469 float y = py - dly * ax - dy * ay;
472 nsvg__addEdge(r, prevx, prevy, x, y);
480 else if (i == ncap - 1) {
486 nsvg__addEdge(r, left->x, left->y, lx, ly);
487 nsvg__addEdge(r, rx, ry, right->x, right->y);
490 left->x = lx; left->y = ly;
491 right->x = rx; right->y = ry;
494static void nsvg__bevelJoin(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1,
float lineWidth)
496 float w = lineWidth * 0.5f;
497 float dlx0 = p0->dy, dly0 = -p0->dx;
498 float dlx1 = p1->dy, dly1 = -p1->dx;
499 float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w);
500 float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w);
501 float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w);
502 float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w);
504 nsvg__addEdge(r, lx0, ly0, left->x, left->y);
505 nsvg__addEdge(r, lx1, ly1, lx0, ly0);
507 nsvg__addEdge(r, right->x, right->y, rx0, ry0);
508 nsvg__addEdge(r, rx0, ry0, rx1, ry1);
510 left->x = lx1; left->y = ly1;
511 right->x = rx1; right->y = ry1;
514static void nsvg__miterJoin(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1,
float lineWidth)
516 float w = lineWidth * 0.5f;
517 float dlx0 = p0->dy, dly0 = -p0->dx;
518 float dlx1 = p1->dy, dly1 = -p1->dx;
519 float lx0, rx0, lx1, rx1;
520 float ly0, ry0, ly1, ry1;
522 if (p1->flags & NSVG_PT_LEFT) {
523 lx0 = lx1 = p1->x - p1->dmx * w;
524 ly0 = ly1 = p1->y - p1->dmy * w;
525 nsvg__addEdge(r, lx1, ly1, left->x, left->y);
527 rx0 = p1->x + (dlx0 * w);
528 ry0 = p1->y + (dly0 * w);
529 rx1 = p1->x + (dlx1 * w);
530 ry1 = p1->y + (dly1 * w);
531 nsvg__addEdge(r, right->x, right->y, rx0, ry0);
532 nsvg__addEdge(r, rx0, ry0, rx1, ry1);
535 lx0 = p1->x - (dlx0 * w);
536 ly0 = p1->y - (dly0 * w);
537 lx1 = p1->x - (dlx1 * w);
538 ly1 = p1->y - (dly1 * w);
539 nsvg__addEdge(r, lx0, ly0, left->x, left->y);
540 nsvg__addEdge(r, lx1, ly1, lx0, ly0);
542 rx0 = rx1 = p1->x + p1->dmx * w;
543 ry0 = ry1 = p1->y + p1->dmy * w;
544 nsvg__addEdge(r, right->x, right->y, rx1, ry1);
547 left->x = lx1; left->y = ly1;
548 right->x = rx1; right->y = ry1;
551static void nsvg__roundJoin(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1,
float lineWidth,
int ncap)
554 float w = lineWidth * 0.5f;
555 float dlx0 = p0->dy, dly0 = -p0->dx;
556 float dlx1 = p1->dy, dly1 = -p1->dx;
557 float a0 =
atan2f(dly0, dlx0);
558 float a1 =
atan2f(dly1, dlx1);
560 float lx, ly, rx, ry;
562 if (da < NSVG_PI) da += NSVG_PI * 2;
563 if (da > NSVG_PI) da -= NSVG_PI * 2;
565 n = (int)
ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap);
567 if (n > ncap) n = ncap;
574 for (i = 0; i < n; i++) {
575 float u = (float)i / (
float)(n - 1);
576 float a = a0 + u * da;
577 float ax =
cosf(a) * w, ay =
sinf(a) * w;
578 float lx1 = p1->x - ax, ly1 = p1->y - ay;
579 float rx1 = p1->x + ax, ry1 = p1->y + ay;
581 nsvg__addEdge(r, lx1, ly1, lx, ly);
582 nsvg__addEdge(r, rx, ry, rx1, ry1);
588 left->x = lx; left->y = ly;
589 right->x = rx; right->y = ry;
592static void nsvg__straightJoin(
NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1,
float lineWidth)
594 float w = lineWidth * 0.5f;
595 float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w);
596 float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w);
598 nsvg__addEdge(r, lx, ly, left->x, left->y);
599 nsvg__addEdge(r, right->x, right->y, rx, ry);
601 left->x = lx; left->y = ly;
602 right->x = rx; right->y = ry;
605static int nsvg__curveDivs(
float r,
float arc,
float tol)
607 float da =
acosf(r / (r + tol)) * 2.0f;
608 int divs = (int)
ceilf(arc / da);
609 if (divs < 2) divs = 2;
613static void nsvg__expandStroke(
NSVGrasterizer* r, NSVGpoint* points,
int npoints,
int closed,
int lineJoin,
int lineCap,
float lineWidth)
615 int ncap = nsvg__curveDivs(lineWidth * 0.5f, NSVG_PI, r->tessTol);
616 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 };
623 p0 = &points[npoints - 1];
637 nsvg__initClosed(&left, &right, p0, p1, lineWidth);
643 float dx = p1->x - p0->x;
644 float dy = p1->y - p0->y;
645 nsvg__normalize(&dx, &dy);
647 nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
649 nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
651 nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0);
654 for (j = s; j < e; ++j) {
655 if (p1->flags & NSVG_PT_CORNER) {
657 nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap);
659 nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth);
661 nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth);
664 nsvg__straightJoin(r, &left, &right, p1, lineWidth);
671 nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y);
672 nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y);
676 float dx = p1->x - p0->x;
677 float dy = p1->y - p0->y;
678 nsvg__normalize(&dx, &dy);
680 nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
682 nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
684 nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1);
688static void nsvg__prepareStroke(
NSVGrasterizer* r,
float miterLimit,
int lineJoin)
693 p0 = &r->points[r->npoints - 1];
695 for (i = 0; i < r->npoints; i++) {
697 p0->dx = p1->x - p0->x;
698 p0->dy = p1->y - p0->y;
699 p0->len = nsvg__normalize(&p0->dx, &p0->dy);
705 p0 = &r->points[r->npoints - 1];
707 for (j = 0; j < r->npoints; j++) {
708 float dlx0, dly0, dlx1, dly1, dmr2, cross;
714 p1->dmx = (dlx0 + dlx1) * 0.5f;
715 p1->dmy = (dly0 + dly1) * 0.5f;
716 dmr2 = p1->dmx * p1->dmx + p1->dmy * p1->dmy;
717 if (dmr2 > 0.000001f) {
718 float s2 = 1.0f / dmr2;
727 p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0;
730 cross = p1->dx * p0->dy - p0->dx * p1->dy;
732 p1->flags |= NSVG_PT_LEFT;
735 if (p1->flags & NSVG_PT_CORNER) {
737 p1->flags |= NSVG_PT_BEVEL;
758 nsvg__addPathPoint(r,
path->pts[0] * scale,
path->pts[1] * scale, NSVG_PT_CORNER);
759 for (i = 0; i <
path->npts - 1; i += 3) {
760 float* p = &
path->pts[i * 2];
761 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);
766 closed =
path->closed;
769 p0 = &r->points[r->npoints - 1];
771 if (nsvg__ptEquals(p0->x, p0->y, p1->x, p1->y, r->distTol)) {
773 p0 = &r->points[r->npoints - 1];
778 int idash = 0, dashState = 1;
779 float totalDist = 0, dashLen, allDashLen, dashOffset;
783 nsvg__appendPathPoint(r, r->points[0]);
786 nsvg__duplicatePoints(r);
790 nsvg__appendPathPoint(r, cur);
800 if (dashOffset < 0.0f)
801 dashOffset += allDashLen;
809 for (j = 1; j < r->npoints2; ) {
810 float dx = r->points2[j].x - cur.x;
811 float dy = r->points2[j].y - cur.y;
812 float dist =
sqrtf(dx * dx + dy * dy);
814 if ((totalDist + dist) > dashLen) {
816 float d = (dashLen - totalDist) / dist;
817 float x = cur.x + dx * d;
818 float y = cur.y + dy * d;
819 nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER);
822 if (r->npoints > 1 && dashState) {
823 nsvg__prepareStroke(r, miterLimit, lineJoin);
824 nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
827 dashState = !dashState;
833 cur.flags = NSVG_PT_CORNER;
836 nsvg__appendPathPoint(r, cur);
841 nsvg__appendPathPoint(r, cur);
846 if (r->npoints > 1 && dashState) {
847 nsvg__prepareStroke(r, miterLimit, lineJoin);
848 nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
852 nsvg__prepareStroke(r, miterLimit, lineJoin);
853 nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth);
858static int nsvg__cmpEdge(
const void* p,
const void* q)
860 const NSVGedge* a = (
const NSVGedge*)p;
861 const NSVGedge* b = (
const NSVGedge*)q;
863 if (a->y0 < b->y0)
return -1;
864 if (a->y0 > b->y0)
return 1;
869static NSVGactiveEdge* nsvg__addActive(
NSVGrasterizer* r, NSVGedge* e,
float startPoint)
873 if (r->freelist !=
NULL) {
876 r->freelist = z->next;
880 z = (NSVGactiveEdge*)nsvg__alloc(r,
sizeof(NSVGactiveEdge));
884 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
888 z->dx = (int)(-nsvg__roundf(NSVG__FIX * -dxdy));
890 z->dx = (int)nsvg__roundf(NSVG__FIX * dxdy);
891 z->x = (int)nsvg__roundf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));
902 z->next = r->freelist;
906static void nsvg__fillScanline(
unsigned char* scanline,
int len,
int x0,
int x1,
int maxWeight,
int* xmin,
int* xmax)
908 int i = x0 >> NSVG__FIXSHIFT;
909 int j = x1 >> NSVG__FIXSHIFT;
910 if (i < *xmin) *xmin = i;
911 if (j > *xmax) *xmax = j;
912 if (i < len && j >= 0) {
915 scanline[i] = (
unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT));
919 scanline[i] = (
unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT));
924 scanline[j] = (
unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT));
928 for (++i; i < j; ++i)
929 scanline[i] = (
unsigned char)(scanline[i] + maxWeight);
937static void nsvg__fillActiveEdges(
unsigned char* scanline,
int len, NSVGactiveEdge* e,
int maxWeight,
int* xmin,
int* xmax,
char fillRule)
947 x0 = e->x; w += e->dir;
950 int x1 = e->x; w += e->dir;
953 nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
966 int x1 = e->x; w = 0;
967 nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
974static float nsvg__clampf(
float a,
float mn,
float mx) {
977 return a < mn ? mn : (a > mx ? mx : a);
980static unsigned int nsvg__RGBA(
unsigned char r,
unsigned char g,
unsigned char b,
unsigned char a)
982 return ((
unsigned int)r) | ((
unsigned int)g << 8) | ((
unsigned int)b << 16) | ((
unsigned int)a << 24);
985static unsigned int nsvg__lerpRGBA(
unsigned int c0,
unsigned int c1,
float u)
987 int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
988 int r = (((c0) & 0xff) * (256 - iu) + (((c1) & 0xff) * iu)) >> 8;
989 int g = (((c0 >> 8) & 0xff) * (256 - iu) + (((c1 >> 8) & 0xff) * iu)) >> 8;
990 int b = (((c0 >> 16) & 0xff) * (256 - iu) + (((c1 >> 16) & 0xff) * iu)) >> 8;
991 int a = (((c0 >> 24) & 0xff) * (256 - iu) + (((c1 >> 24) & 0xff) * iu)) >> 8;
992 return nsvg__RGBA((
unsigned char)r, (
unsigned char)g, (
unsigned char)b, (
unsigned char)a);
995static unsigned int nsvg__applyOpacity(
unsigned int c,
float u)
997 int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
999 int g = (c >> 8) & 0xff;
1000 int b = (c >> 16) & 0xff;
1001 int a = (((c >> 24) & 0xff) * iu) >> 8;
1002 return nsvg__RGBA((
unsigned char)r, (
unsigned char)g, (
unsigned char)b, (
unsigned char)a);
1005static inline int nsvg__div255(
int x)
1007 return ((x + 1) * 257) >> 16;
1010static void nsvg__scanlineSolid(
unsigned char* dst,
int count,
unsigned char* cover,
int x,
int y,
1011 float tx,
float ty,
float scale, NSVGcachedPaint* cache)
1015 int i, cr, cg, cb, ca;
1016 cr = cache->colors[0] & 0xff;
1017 cg = (cache->colors[0] >> 8) & 0xff;
1018 cb = (cache->colors[0] >> 16) & 0xff;
1019 ca = (cache->colors[0] >> 24) & 0xff;
1021 for (i = 0; i < count; i++) {
1023 int a = nsvg__div255((
int)cover[0] * ca);
1026 r = nsvg__div255(cr * a);
1027 g = nsvg__div255(cg * a);
1028 b = nsvg__div255(cb * a);
1031 r += nsvg__div255(ia * (
int)dst[0]);
1032 g += nsvg__div255(ia * (
int)dst[1]);
1033 b += nsvg__div255(ia * (
int)dst[2]);
1034 a += nsvg__div255(ia * (
int)dst[3]);
1036 dst[0] = (
unsigned char)r;
1037 dst[1] = (
unsigned char)g;
1038 dst[2] = (
unsigned char)b;
1039 dst[3] = (
unsigned char)a;
1048 float fx, fy, dx, gy;
1049 float*
t = cache->xform;
1050 int i, cr, cg, cb, ca;
1053 fx = ((float)x - tx) / scale;
1054 fy = ((float)y - ty) / scale;
1057 for (i = 0; i < count; i++) {
1059 gy = fx *
t[1] + fy *
t[3] +
t[5];
1060 c = cache->colors[(int)nsvg__clampf(gy * 255.0f, 0, 255.0f)];
1062 cg = (c >> 8) & 0xff;
1063 cb = (c >> 16) & 0xff;
1064 ca = (c >> 24) & 0xff;
1066 a = nsvg__div255((
int)cover[0] * ca);
1070 r = nsvg__div255(cr * a);
1071 g = nsvg__div255(cg * a);
1072 b = nsvg__div255(cb * a);
1075 r += nsvg__div255(ia * (
int)dst[0]);
1076 g += nsvg__div255(ia * (
int)dst[1]);
1077 b += nsvg__div255(ia * (
int)dst[2]);
1078 a += nsvg__div255(ia * (
int)dst[3]);
1080 dst[0] = (
unsigned char)r;
1081 dst[1] = (
unsigned char)g;
1082 dst[2] = (
unsigned char)b;
1083 dst[3] = (
unsigned char)a;
1094 float fx, fy, dx, gx, gy, gd;
1095 float*
t = cache->xform;
1096 int i, cr, cg, cb, ca;
1099 fx = ((float)x - tx) / scale;
1100 fy = ((float)y - ty) / scale;
1103 for (i = 0; i < count; i++) {
1105 gx = fx *
t[0] + fy *
t[2] +
t[4];
1106 gy = fx *
t[1] + fy *
t[3] +
t[5];
1107 gd =
sqrtf(gx * gx + gy * gy);
1108 c = cache->colors[(int)nsvg__clampf(gd * 255.0f, 0, 255.0f)];
1110 cg = (c >> 8) & 0xff;
1111 cb = (c >> 16) & 0xff;
1112 ca = (c >> 24) & 0xff;
1114 a = nsvg__div255((
int)cover[0] * ca);
1118 r = nsvg__div255(cr * a);
1119 g = nsvg__div255(cg * a);
1120 b = nsvg__div255(cb * a);
1123 r += nsvg__div255(ia * (
int)dst[0]);
1124 g += nsvg__div255(ia * (
int)dst[1]);
1125 b += nsvg__div255(ia * (
int)dst[2]);
1126 a += nsvg__div255(ia * (
int)dst[3]);
1128 dst[0] = (
unsigned char)r;
1129 dst[1] = (
unsigned char)g;
1130 dst[2] = (
unsigned char)b;
1131 dst[3] = (
unsigned char)a;
1140static void nsvg__rasterizeSortedEdges(
NSVGrasterizer* r,
float tx,
float ty,
float scale, NSVGcachedPaint* cache,
char fillRule)
1142 NSVGactiveEdge* active =
NULL;
1145 int maxWeight = (255 / NSVG__SUBSAMPLES);
1148 for (y = 0; y < r->height; y++) {
1149 memset(r->scanline, 0, r->width);
1152 for (s = 0; s < NSVG__SUBSAMPLES; ++s) {
1154 float scany = (float)(y * NSVG__SUBSAMPLES + s) + 0.5f;
1155 NSVGactiveEdge** step = &active;
1160 NSVGactiveEdge* z = *step;
1161 if (z->ey <= scany) {
1164 nsvg__freeActive(r, z);
1168 step = &((*step)->next);
1176 while (*step && (*step)->next) {
1177 if ((*step)->x > (*step)->next->x) {
1178 NSVGactiveEdge*
t = *step;
1179 NSVGactiveEdge* q =
t->next;
1185 step = &(*step)->next;
1187 if (!changed)
break;
1191 while (e < r->nedges && r->edges[e].y0 <= scany) {
1192 if (r->edges[e].y1 > scany) {
1193 NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany);
1194 if (z ==
NULL)
break;
1196 if (active ==
NULL) {
1199 else if (z->x < active->x) {
1206 NSVGactiveEdge* p = active;
1207 while (p->next && p->next->x < z->x)
1219 nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule);
1222 if (xmin < 0) xmin = 0;
1223 if (xmax > r->width - 1) xmax = r->width - 1;
1225 nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin * 4, xmax - xmin + 1, &r->scanline[xmin], xmin, y, tx, ty, scale, cache);
1231static void nsvg__unpremultiplyAlpha(
unsigned char* image,
int w,
int h,
int stride)
1236 for (y = 0; y < h; y++) {
1237 unsigned char* row = &image[y * stride];
1238 for (x = 0;
x < w;
x++) {
1239 int r = row[0], g = row[1], b = row[2], a = row[3];
1241 row[0] = (
unsigned char)(r * 255 / a);
1242 row[1] = (
unsigned char)(g * 255 / a);
1243 row[2] = (
unsigned char)(b * 255 / a);
1250 for (y = 0; y < h; y++) {
1251 unsigned char* row = &image[y * stride];
1252 for (x = 0;
x < w;
x++) {
1253 int r = 0, g = 0, b = 0, a = row[3], n = 0;
1255 if (x - 1 > 0 && row[-1] != 0) {
1261 if (x + 1 < w && row[7] != 0) {
1267 if (y - 1 > 0 && row[-stride + 3] != 0) {
1269 g += row[-stride + 1];
1270 b += row[-stride + 2];
1273 if (y + 1 < h && row[stride + 3] != 0) {
1275 g += row[stride + 1];
1276 b += row[stride + 2];
1280 row[0] = (
unsigned char)(r / n);
1281 row[1] = (
unsigned char)(g / n);
1282 row[2] = (
unsigned char)(b / n);
1291static void nsvg__initPaint(NSVGcachedPaint* cache,
NSVGpaint* paint,
float opacity)
1296 cache->type = paint->
type;
1299 cache->colors[0] = nsvg__applyOpacity(paint->
color, opacity);
1305 cache->spread = grad->
spread;
1306 memcpy(cache->xform, grad->
xform,
sizeof(
float) * 6);
1309 for (i = 0; i < 256; i++)
1310 cache->colors[i] = 0;
1312 else if (grad->
nstops == 1) {
1313 unsigned int color = nsvg__applyOpacity(grad->
stops[0].
color, opacity);
1314 for (i = 0; i < 256; i++)
1315 cache->colors[i] = color;
1318 unsigned int ca, cb = 0;
1319 float ua, ub, du, u;
1322 ca = nsvg__applyOpacity(grad->
stops[0].
color, opacity);
1325 ia = (int)(ua * 255.0f);
1326 ib = (int)(ub * 255.0f);
1327 for (i = 0; i < ia; i++) {
1328 cache->colors[i] = ca;
1331 for (i = 0; i < grad->
nstops - 1; i++) {
1332 ca = nsvg__applyOpacity(grad->
stops[i].
color, opacity);
1333 cb = nsvg__applyOpacity(grad->
stops[i + 1].
color, opacity);
1335 ub = nsvg__clampf(grad->
stops[i + 1].
offset, 0, 1);
1336 ia = (int)(ua * 255.0f);
1337 ib = (int)(ub * 255.0f);
1339 if (count <= 0)
continue;
1341 du = 1.0f / (float)count;
1342 for (j = 0; j < count; j++) {
1343 cache->colors[ia + j] = nsvg__lerpRGBA(ca, cb, u);
1348 for (i = ib; i < 256; i++)
1349 cache->colors[i] = cb;
1397 NSVGimage* image,
float tx,
float ty,
float scale,
1398 unsigned char* dst,
int w,
int h,
int stride)
1402 NSVGcachedPaint cache;
1405 unsigned char paintOrder;
1412 if (w > r->cscanline) {
1414 r->scanline = (
unsigned char*)
realloc(r->scanline, w);
1415 if (r->scanline ==
NULL)
return;
1418 for (i = 0; i < h; i++)
1419 memset(&dst[i * stride], 0, w * 4);
1421 for (shape = image->
shapes; shape !=
NULL; shape = shape->
next) {
1425 for (j = 0; j < 3; j++) {
1426 paintOrder = (shape->
paintOrder >> (2 * j)) & 0x03;
1433 nsvg__flattenShape(r, shape, scale);
1436 for (i = 0; i < r->nedges; i++) {
1439 e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
1441 e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
1446 qsort(r->edges, r->nedges,
sizeof(NSVGedge), nsvg__cmpEdge);
1449 nsvg__initPaint(&cache, &shape->
fill, shape->
opacity);
1451 nsvg__rasterizeSortedEdges(r, tx, ty, scale, &cache, shape->
fillRule);
1458 nsvg__flattenShapeStroke(r, shape, scale);
1463 for (i = 0; i < r->nedges; i++) {
1466 e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
1468 e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
1473 qsort(r->edges, r->nedges,
sizeof(NSVGedge), nsvg__cmpEdge);
1483 nsvg__unpremultiplyAlpha(dst, w, h, stride);
XE_LIB int connect(int sockfd, sockaddr_ *addr, socklen_t addrlen)
XETime t
Definition main.cpp:53
char * path
Definition main.cpp:66
void * memcpy(void *Dest, const void *Src, ACPI_SIZE Count)
Definition utclib.c:310
void * memset(void *Dest, int Value, ACPI_SIZE Count)
Definition utclib.c:346
float acosf(float x)
Definition acosf.cpp:50
#define NULL
Definition actypes.h:561
float atan2f(float y, float x)
Definition atan2f.cpp:36
float ceilf(float x)
Definition ceilf.cpp:3
float fmodf(float x, float y)
Definition fmodf.cpp:7
#define isnan(x)
Definition math.h:161
XE_LIB float floorf(float)
Definition math.cpp:139
XE_LIB float sqrtf(float x)
Definition math.cpp:304
XE_LIB float sinf(float)
Definition math.cpp:227
XE_LIB float cosf(float)
Definition math.cpp:85
@ 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
XE_LIB void * realloc(void *address, unsigned int new_size)
Definition _heap.cpp:6420
XE_LIB void qsort(void *base, size_t num, size_t size, int(*comparator)(const void *, const void *))
Definition qsort.cpp:80
unsigned int color
Definition nanosvg.h:116
float offset
Definition nanosvg.h:117
float xform[6]
Definition nanosvg.h:121
int nstops
Definition nanosvg.h:124
char spread
Definition nanosvg.h:122
NSVGgradientStop stops[1]
Definition nanosvg.h:125
NSVGshape * shapes
Definition nanosvg.h:173
unsigned int color
Definition nanosvg.h:131
NSVGgradient * gradient
Definition nanosvg.h:132
signed char type
Definition nanosvg.h:129
NSVGpath * paths
Definition nanosvg.h:165
float miterLimit
Definition nanosvg.h:157
char strokeLineCap
Definition nanosvg.h:156
char strokeDashCount
Definition nanosvg.h:154
float opacity
Definition nanosvg.h:150
NSVGpaint fill
Definition nanosvg.h:148
struct NSVGshape * next
Definition nanosvg.h:166
char strokeLineJoin
Definition nanosvg.h:155
float strokeDashArray[8]
Definition nanosvg.h:153
float strokeWidth
Definition nanosvg.h:151
unsigned char flags
Definition nanosvg.h:160
float strokeDashOffset
Definition nanosvg.h:152
NSVGpaint stroke
Definition nanosvg.h:149
char fillRule
Definition nanosvg.h:158
unsigned char paintOrder
Definition nanosvg.h:159
int x
Definition term.cpp:49
void * malloc(unsigned nSize)
Definition uspios.c:31
void free(void *pBlock)
Definition uspios.c:35