30#ifndef NANOSVGRAST_CPLUSPLUS 
   36typedef struct NSVGrasterizer NSVGrasterizer;
 
   52NSVGrasterizer* nsvgCreateRasterizer(
void);
 
   63void nsvgRasterize(NSVGrasterizer* r,
 
   64                   NSVGimage* image, 
float tx, 
float ty, 
float scale,
 
   65                   unsigned char* dst, 
int w, 
int h, 
int stride);
 
   68void nsvgDeleteRasterizer(NSVGrasterizer*);
 
   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;
 
  153NSVGrasterizer* nsvgCreateRasterizer(
void)
 
  155    NSVGrasterizer* r = (NSVGrasterizer*)malloc(
sizeof(NSVGrasterizer));
 
  156    if (r == NULL) 
goto error;
 
  157    memset(r, 0, 
sizeof(NSVGrasterizer));
 
  165    nsvgDeleteRasterizer(r);
 
  169void nsvgDeleteRasterizer(NSVGrasterizer* r)
 
  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));
 
  201    if (newp == NULL) 
return NULL;
 
  202    memset(newp, 0, 
sizeof(NSVGmemPage));
 
  213static void nsvg__resetPool(NSVGrasterizer* r)
 
  215    NSVGmemPage* p = r->pages;
 
  220    r->curpage = r->pages;
 
  223static unsigned char* nsvg__alloc(NSVGrasterizer* r, 
int size)
 
  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;
 
  267static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt)
 
  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;
 
  278static void nsvg__duplicatePoints(NSVGrasterizer* r)
 
  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); }
 
  336static void nsvg__flattenCubicBez(NSVGrasterizer* r,
 
  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);
 
  374static void nsvg__flattenShape(NSVGrasterizer* r, 
NSVGshape* shape, 
float scale)
 
  379    for (path = shape->paths; path != NULL; path = path->next) {
 
  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;
 
  466        float ax = cosf(a) * w, ay = sinf(a) * w;
 
  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);
 
  574        float ax = cosf(a) * w, ay = sinf(a) * w;
 
  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);
 
  641        if (lineCap == NSVG_CAP_BUTT)
 
  642            nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
 
  643        else if (lineCap == NSVG_CAP_SQUARE)
 
  644            nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
 
  645        else if (lineCap == NSVG_CAP_ROUND)
 
  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) {
 
  651            if (lineJoin == NSVG_JOIN_ROUND)
 
  652                nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap);
 
  653            else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL))
 
  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);
 
  672        if (lineCap == NSVG_CAP_BUTT)
 
  673            nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
 
  674        else if (lineCap == NSVG_CAP_SQUARE)
 
  675            nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
 
  676        else if (lineCap == NSVG_CAP_ROUND)
 
  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) {
 
  729            if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) {
 
  730                p1->flags |= NSVG_PT_BEVEL;
 
  738static void nsvg__flattenShapeStroke(NSVGrasterizer* r, 
NSVGshape* shape, 
float scale)
 
  743    float miterLimit = shape->miterLimit;
 
  744    int lineJoin = shape->strokeLineJoin;
 
  745    int lineCap = shape->strokeLineCap;
 
  746    float lineWidth = shape->strokeWidth * scale;
 
  748    for (path = shape->paths; path != NULL; path = path->next) {
 
  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__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
 
  841            nsvg__prepareStroke(r, miterLimit, lineJoin);
 
  842            nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth);
 
  847static int nsvg__cmpEdge(
const void *p, 
const void *q)
 
  849    const NSVGedge* a = (
const NSVGedge*)p;
 
  850    const NSVGedge* b = (
const NSVGedge*)q;
 
  852    if (a->y0 < b->y0) 
return -1;
 
  853    if (a->y0 > b->y0) 
return  1;
 
  858static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, 
float startPoint)
 
  862    if (r->freelist != NULL) {
 
  865        r->freelist = z->next;
 
  868        z = (NSVGactiveEdge*)nsvg__alloc(r, 
sizeof(NSVGactiveEdge));
 
  869        if (z == NULL) 
return NULL;
 
  872    float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
 
  876        z->dx = (int)(-nsvg__roundf(NSVG__FIX * -dxdy));
 
  878        z->dx = (int)nsvg__roundf(NSVG__FIX * dxdy);
 
  879    z->x = (int)nsvg__roundf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));
 
  888static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z)
 
  890    z->next = r->freelist;
 
  894static void nsvg__fillScanline(
unsigned char* scanline, 
int len, 
int x0, 
int x1, 
int maxWeight, 
int* xmin, 
int* xmax)
 
  896    int i = x0 >> NSVG__FIXSHIFT;
 
  897    int j = x1 >> NSVG__FIXSHIFT;
 
  898    if (i < *xmin) *xmin = i;
 
  899    if (j > *xmax) *xmax = j;
 
  900    if (i < len && j >= 0) {
 
  903            scanline[i] = (
unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT));
 
  906                scanline[i] = (
unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT));
 
  911                scanline[j] = (
unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT));
 
  915            for (++i; i < j; ++i) 
 
  916                scanline[i] = (
unsigned char)(scanline[i] + maxWeight);
 
  924static void nsvg__fillActiveEdges(
unsigned char* scanline, 
int len, NSVGactiveEdge* e, 
int maxWeight, 
int* xmin, 
int* xmax, 
char fillRule)
 
  929    if (fillRule == NSVG_FILLRULE_NONZERO) {
 
  934                x0 = e->x; w += e->dir;
 
  936                int x1 = e->x; w += e->dir;
 
  939                    nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
 
  943    } 
else if (fillRule == NSVG_FILLRULE_EVENODD) {
 
  950                int x1 = e->x; w = 0;
 
  951                nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
 
  958static float nsvg__clampf(
float a, 
float mn, 
float mx) { 
return a < mn ? mn : (a > mx ? mx : a); }
 
  960static unsigned int nsvg__RGBA(
unsigned char r, 
unsigned char g, 
unsigned char b, 
unsigned char a)
 
  962    return ((
unsigned int)r) | ((
unsigned int)g << 8) | ((
unsigned int)b << 16) | ((
unsigned int)a << 24);
 
  965static unsigned int nsvg__lerpRGBA(
unsigned int c0, 
unsigned int c1, 
float u)
 
  967    int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
 
  968    int r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8;
 
  969    int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8;
 
  970    int b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8;
 
  971    int a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8;
 
  972    return nsvg__RGBA((
unsigned char)r, (
unsigned char)g, (
unsigned char)b, (
unsigned char)a);
 
  975static unsigned int nsvg__applyOpacity(
unsigned int c, 
float u)
 
  977    int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
 
  979    int g = (c>>8) & 0xff;
 
  980    int b = (c>>16) & 0xff;
 
  981    int a = (((c>>24) & 0xff)*iu) >> 8;
 
  982    return nsvg__RGBA((
unsigned char)r, (
unsigned char)g, (
unsigned char)b, (
unsigned char)a);
 
  985static inline int nsvg__div255(
int x)
 
  987    return ((x+1) * 257) >> 16;
 
  990static void nsvg__scanlineSolid(
unsigned char* dst, 
int count, 
unsigned char* cover, 
int x, 
int y,
 
  991                                float tx, 
float ty, 
float scale, NSVGcachedPaint* cache)
 
  994    if (cache->type == NSVG_PAINT_COLOR) {
 
  995        int i, cr, cg, cb, ca;
 
  996        cr = cache->colors[0] & 0xff;
 
  997        cg = (cache->colors[0] >> 8) & 0xff;
 
  998        cb = (cache->colors[0] >> 16) & 0xff;
 
  999        ca = (cache->colors[0] >> 24) & 0xff;
 
 1001        for (i = 0; i < count; i++) {
 
 1003            int a = nsvg__div255((
int)cover[0] * ca);
 
 1006            r = nsvg__div255(cr * a);
 
 1007            g = nsvg__div255(cg * a);
 
 1008            b = nsvg__div255(cb * a);
 
 1011            r += nsvg__div255(ia * (
int)dst[0]);
 
 1012            g += nsvg__div255(ia * (
int)dst[1]);
 
 1013            b += nsvg__div255(ia * (
int)dst[2]);
 
 1014            a += nsvg__div255(ia * (
int)dst[3]);
 
 1016            dst[0] = (
unsigned char)r;
 
 1017            dst[1] = (
unsigned char)g;
 
 1018            dst[2] = (
unsigned char)b;
 
 1019            dst[3] = (
unsigned char)a;
 
 1024    } 
else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) {
 
 1027        float fx, fy, dx, gy;
 
 1028        float* t = cache->xform;
 
 1029        int i, cr, cg, cb, ca;
 
 1032        fx = ((float)x - tx) / scale;
 
 1033        fy = ((float)y - ty) / scale;
 
 1036        for (i = 0; i < count; i++) {
 
 1038            gy = fx*t[1] + fy*t[3] + t[5];
 
 1039            c = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)];
 
 1041            cg = (c >> 8) & 0xff;
 
 1042            cb = (c >> 16) & 0xff;
 
 1043            ca = (c >> 24) & 0xff;
 
 1045            a = nsvg__div255((
int)cover[0] * ca);
 
 1049            r = nsvg__div255(cr * a);
 
 1050            g = nsvg__div255(cg * a);
 
 1051            b = nsvg__div255(cb * a);
 
 1054            r += nsvg__div255(ia * (
int)dst[0]);
 
 1055            g += nsvg__div255(ia * (
int)dst[1]);
 
 1056            b += nsvg__div255(ia * (
int)dst[2]);
 
 1057            a += nsvg__div255(ia * (
int)dst[3]);
 
 1059            dst[0] = (
unsigned char)r;
 
 1060            dst[1] = (
unsigned char)g;
 
 1061            dst[2] = (
unsigned char)b;
 
 1062            dst[3] = (
unsigned char)a;
 
 1068    } 
else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) {
 
 1072        float fx, fy, dx, gx, gy, gd;
 
 1073        float* t = cache->xform;
 
 1074        int i, cr, cg, cb, ca;
 
 1077        fx = ((float)x - tx) / scale;
 
 1078        fy = ((float)y - ty) / scale;
 
 1081        for (i = 0; i < count; i++) {
 
 1083            gx = fx*t[0] + fy*t[2] + t[4];
 
 1084            gy = fx*t[1] + fy*t[3] + t[5];
 
 1085            gd = sqrtf(gx*gx + gy*gy);
 
 1086            c = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)];
 
 1088            cg = (c >> 8) & 0xff;
 
 1089            cb = (c >> 16) & 0xff;
 
 1090            ca = (c >> 24) & 0xff;
 
 1092            a = nsvg__div255((
int)cover[0] * ca);
 
 1096            r = nsvg__div255(cr * a);
 
 1097            g = nsvg__div255(cg * a);
 
 1098            b = nsvg__div255(cb * a);
 
 1101            r += nsvg__div255(ia * (
int)dst[0]);
 
 1102            g += nsvg__div255(ia * (
int)dst[1]);
 
 1103            b += nsvg__div255(ia * (
int)dst[2]);
 
 1104            a += nsvg__div255(ia * (
int)dst[3]);
 
 1106            dst[0] = (
unsigned char)r;
 
 1107            dst[1] = (
unsigned char)g;
 
 1108            dst[2] = (
unsigned char)b;
 
 1109            dst[3] = (
unsigned char)a;
 
 1118static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, 
float tx, 
float ty, 
float scale, NSVGcachedPaint* cache, 
char fillRule)
 
 1120    NSVGactiveEdge *active = NULL;
 
 1123    int maxWeight = (255 / NSVG__SUBSAMPLES);  
 
 1126    for (y = 0; y < r->height; y++) {
 
 1127        memset(r->scanline, 0, r->width);
 
 1130        for (s = 0; s < NSVG__SUBSAMPLES; ++s) {
 
 1132            float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f;
 
 1133            NSVGactiveEdge **step = &active;
 
 1138                NSVGactiveEdge *z = *step;
 
 1139                if (z->ey <= scany) {
 
 1142                    nsvg__freeActive(r, z);
 
 1145                    step = &((*step)->next); 
 
 1153                while (*step && (*step)->next) {
 
 1154                    if ((*step)->x > (*step)->next->x) {
 
 1155                        NSVGactiveEdge* t = *step;
 
 1156                        NSVGactiveEdge* q = t->next;
 
 1162                    step = &(*step)->next;
 
 1164                if (!changed) 
break;
 
 1168            while (e < r->nedges && r->edges[e].y0 <= scany) {
 
 1169                if (r->edges[e].y1 > scany) {
 
 1170                    NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany);
 
 1171                    if (z == NULL) 
break;
 
 1173                    if (active == NULL) {
 
 1175                    } 
else if (z->x < active->x) {
 
 1181                        NSVGactiveEdge* p = active;
 
 1182                        while (p->next && p->next->x < z->x)
 
 1194                nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule);
 
 1197        if (xmin < 0) xmin = 0;
 
 1198        if (xmax > r->width-1) xmax = r->width-1;
 
 1200            nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scale, cache);
 
 1206static void nsvg__unpremultiplyAlpha(
unsigned char* image, 
int w, 
int h, 
int stride)
 
 1211    for (y = 0; y < h; y++) {
 
 1212        unsigned char *row = &image[y*stride];
 
 1213        for (x = 0; x < w; x++) {
 
 1214            int r = row[0], g = row[1], b = row[2], a = row[3];
 
 1216                row[0] = (
unsigned char)(r*255/a);
 
 1217                row[1] = (
unsigned char)(g*255/a);
 
 1218                row[2] = (
unsigned char)(b*255/a);
 
 1225    for (y = 0; y < h; y++) {
 
 1226        unsigned char *row = &image[y*stride];
 
 1227        for (x = 0; x < w; x++) {
 
 1228            int r = 0, g = 0, b = 0, a = row[3], n = 0;
 
 1230                if (x-1 > 0 && row[-1] != 0) {
 
 1236                if (x+1 < w && row[7] != 0) {
 
 1242                if (y-1 > 0 && row[-stride+3] != 0) {
 
 1244                    g += row[-stride+1];
 
 1245                    b += row[-stride+2];
 
 1248                if (y+1 < h && row[stride+3] != 0) {
 
 1255                    row[0] = (
unsigned char)(r/n);
 
 1256                    row[1] = (
unsigned char)(g/n);
 
 1257                    row[2] = (
unsigned char)(b/n);
 
 1266static void nsvg__initPaint(NSVGcachedPaint* cache, 
NSVGpaint* paint, 
float opacity)
 
 1271    cache->type = paint->type;
 
 1273    if (paint->type == NSVG_PAINT_COLOR) {
 
 1274        cache->colors[0] = nsvg__applyOpacity(paint->color, opacity);
 
 1278    grad = paint->gradient;
 
 1280    cache->spread = grad->spread;
 
 1281    memcpy(cache->xform, grad->xform, 
sizeof(
float)*6);
 
 1283    if (grad->nstops == 0) {
 
 1284        for (i = 0; i < 256; i++)
 
 1285            cache->colors[i] = 0;
 
 1286    } 
else if (grad->nstops == 1) {
 
 1287        unsigned int color = nsvg__applyOpacity(grad->stops[0].color, opacity);
 
 1288        for (i = 0; i < 256; i++)
 
 1289            cache->colors[i] = color;
 
 1291        unsigned int ca, cb = 0;
 
 1292        float ua, ub, du, u;
 
 1295        ca = nsvg__applyOpacity(grad->stops[0].color, opacity);
 
 1296        ua = nsvg__clampf(grad->stops[0].offset, 0, 1);
 
 1297        ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1);
 
 1298        ia = (int)(ua * 255.0f);
 
 1299        ib = (int)(ub * 255.0f);
 
 1300        for (i = 0; i < ia; i++) {
 
 1301            cache->colors[i] = ca;
 
 1304        for (i = 0; i < grad->nstops-1; i++) {
 
 1305            ca = nsvg__applyOpacity(grad->stops[i].color, opacity);
 
 1306            cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity);
 
 1307            ua = nsvg__clampf(grad->stops[i].offset, 0, 1);
 
 1308            ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1);
 
 1309            ia = (int)(ua * 255.0f);
 
 1310            ib = (int)(ub * 255.0f);
 
 1312            if (count <= 0) 
continue;
 
 1314            du = 1.0f / (float)count;
 
 1315            for (j = 0; j < count; j++) {
 
 1316                cache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u);
 
 1321        for (i = ib; i < 256; i++)
 
 1322            cache->colors[i] = cb;
 
 1369void nsvgRasterize(NSVGrasterizer* r,
 
 1370                   NSVGimage* image, 
float tx, 
float ty, 
float scale,
 
 1371                   unsigned char* dst, 
int w, 
int h, 
int stride)
 
 1375    NSVGcachedPaint cache;
 
 1383    if (w > r->cscanline) {
 
 1385        r->scanline = (
unsigned char*)realloc(r->scanline, w);
 
 1386        if (r->scanline == NULL) 
return;
 
 1389    for (i = 0; i < h; i++)
 
 1390        memset(&dst[i*stride], 0, w*4);
 
 1392    for (shape = image->shapes; shape != NULL; shape = shape->next) {
 
 1393        if (!(shape->flags & NSVG_FLAGS_VISIBLE))
 
 1396        if (shape->fill.type != NSVG_PAINT_NONE) {
 
 1401            nsvg__flattenShape(r, shape, scale);
 
 1404            for (i = 0; i < r->nedges; i++) {
 
 1407                e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
 
 1409                e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
 
 1414                qsort(r->edges, r->nedges, 
sizeof(NSVGedge), nsvg__cmpEdge);
 
 1417            nsvg__initPaint(&cache, &shape->fill, shape->opacity);
 
 1419            nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, shape->fillRule);
 
 1421        if (shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) {
 
 1426            nsvg__flattenShapeStroke(r, shape, scale);
 
 1431            for (i = 0; i < r->nedges; i++) {
 
 1434                e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
 
 1436                e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
 
 1441                qsort(r->edges, r->nedges, 
sizeof(NSVGedge), nsvg__cmpEdge);
 
 1444            nsvg__initPaint(&cache, &shape->stroke, shape->opacity);
 
 1446            nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, NSVG_FILLRULE_NONZERO);
 
 1450    nsvg__unpremultiplyAlpha(dst, w, h, stride);
 
Definition: nanosvg.h:114
Definition: nanosvg.h:163
Definition: nanosvg.h:122
Definition: nanosvg.h:131
Definition: nanosvg.h:140