diff options
Diffstat (limited to 'generic/nanosvgrast.h')
-rw-r--r-- | generic/nanosvgrast.h | 200 |
1 files changed, 101 insertions, 99 deletions
diff --git a/generic/nanosvgrast.h b/generic/nanosvgrast.h index 2720ce5..b288bcf 100644 --- a/generic/nanosvgrast.h +++ b/generic/nanosvgrast.h @@ -59,23 +59,24 @@ typedef struct NSVGrasterizer NSVGrasterizer; nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4); */ -// Allocated rasterizer context. +/* Allocated rasterizer context. */ NANOSVG_SCOPE NSVGrasterizer* nsvgCreateRasterizer(void); -// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) -// r - pointer to rasterizer context -// image - pointer to image to rasterize -// tx,ty - image offset (applied after scaling) -// scale - image scale -// dst - pointer to destination image data, 4 bytes per pixel (RGBA) -// w - width of the image to render -// h - height of the image to render -// stride - number of bytes per scaleline in the destination buffer +/* Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) + * r - pointer to rasterizer context + * image - pointer to image to rasterize + * tx,ty - image offset (applied after scaling) + * scale - image scale + * dst - pointer to destination image data, 4 bytes per pixel (RGBA) + * w - width of the image to render + * h - height of the image to render + * stride - number of bytes per scaleline in the destination buffer NANOSVG_SCOPE void nsvgRasterize(NSVGrasterizer* r, NSVGimage* image, float tx, float ty, float scale, unsigned char* dst, int w, int h, int stride); + */ -// Deletes rasterizer context. +/* Deletes rasterizer context. */ NANOSVG_SCOPE void nsvgDeleteRasterizer(NSVGrasterizer*); @@ -83,7 +84,7 @@ NANOSVG_SCOPE void nsvgDeleteRasterizer(NSVGrasterizer*); } #endif -#endif // NANOSVGRAST_H +#endif /* NANOSVGRAST_H */ #ifdef NANOSVGRAST_IMPLEMENTATION @@ -202,17 +203,17 @@ static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur) { NSVGmemPage *newp; - // If using existing chain, return the next page in chain + /* If using existing chain, return the next page in chain */ if (cur != NULL && cur->next != NULL) { return cur->next; } - // Alloc new page + /* Alloc new page */ newp = (NSVGmemPage*)NANOSVG_malloc(sizeof(NSVGmemPage)); if (newp == NULL) return NULL; memset(newp, 0, sizeof(NSVGmemPage)); - // Add to linked list + /* Add to linked list */ if (cur != NULL) cur->next = newp; else @@ -302,7 +303,7 @@ static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float { NSVGedge* e; - // Skip horizontal edges + /* Skip horizontal edges */ if (y0 == y1) return; @@ -388,15 +389,15 @@ static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale) for (path = shape->paths; path != NULL; path = path->next) { r->npoints = 0; - // Flatten path + /* Flatten path */ nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0); for (i = 0; i < path->npts-1; i += 3) { float* p = &path->pts[i*2]; 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); } - // Close path + /* Close path */ nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0); - // Build edges + /* Build edges */ for (i = 0, j = r->npoints-1; i < r->npoints; j = i++) nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y); } @@ -619,20 +620,20 @@ static int nsvg__curveDivs(float r, float arc, float tol) static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth) { - int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol); // Calculate divisions per half circle. + int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol); /* Calculate divisions per half circle. */ 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}; NSVGpoint* p0, *p1; int j, s, e; - // Build stroke edges + /* Build stroke edges */ if (closed) { - // Looping + /* Looping */ p0 = &points[npoints-1]; p1 = &points[0]; s = 0; e = npoints; } else { - // Add cap + /* Add cap */ p0 = &points[0]; p1 = &points[1]; s = 1; @@ -644,7 +645,7 @@ static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints firstLeft = left; firstRight = right; } else { - // Add cap + /* Add cap */ float dx = p1->x - p0->x; float dy = p1->y - p0->y; nsvg__normalize(&dx, &dy); @@ -671,11 +672,11 @@ static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints } if (closed) { - // Loop it + /* Loop it */ nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y); nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y); } else { - // Add cap + /* Add cap */ float dx = p1->x - p0->x; float dy = p1->y - p0->y; nsvg__normalize(&dx, &dy); @@ -696,15 +697,15 @@ static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoi p0 = &r->points[r->npoints-1]; p1 = &r->points[0]; for (i = 0; i < r->npoints; i++) { - // Calculate segment direction and length + /* Calculate segment direction and length */ p0->dx = p1->x - p0->x; p0->dy = p1->y - p0->y; p0->len = nsvg__normalize(&p0->dx, &p0->dy); - // Advance + /* Advance */ p0 = p1++; } - // calculate joins + /* calculate joins */ p0 = &r->points[r->npoints-1]; p1 = &r->points[0]; for (j = 0; j < r->npoints; j++) { @@ -713,7 +714,7 @@ static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoi dly0 = -p0->dx; dlx1 = p1->dy; dly1 = -p1->dx; - // Calculate extrusions + /* Calculate extrusions */ p1->dmx = (dlx0 + dlx1) * 0.5f; p1->dmy = (dly0 + dly1) * 0.5f; dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy; @@ -726,15 +727,15 @@ static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoi p1->dmy *= s2; } - // Clear flags, but keep the corner. + /* Clear flags, but keep the corner. */ p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0; - // Keep track of left turns. + /* Keep track of left turns. */ cross = p1->dx * p0->dy - p0->dx * p1->dy; if (cross > 0.0f) p1->flags |= NSVG_PT_LEFT; - // Check to see if the corner needs to be beveled. + /* Check to see if the corner needs to be beveled. */ if (p1->flags & NSVG_PT_CORNER) { if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) { p1->flags |= NSVG_PT_BEVEL; @@ -756,7 +757,7 @@ static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float float lineWidth = shape->strokeWidth * scale; for (path = shape->paths; path != NULL; path = path->next) { - // Flatten path + /* Flatten path */ r->npoints = 0; nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, NSVG_PT_CORNER); for (i = 0; i < path->npts-1; i += 3) { @@ -768,7 +769,7 @@ static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float closed = path->closed; - // If the first and last points are the same, remove the last, mark as closed path. + /* If the first and last points are the same, remove the last, mark as closed path. */ p0 = &r->points[r->npoints-1]; p1 = &r->points[0]; if (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) { @@ -785,20 +786,20 @@ static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float if (closed) nsvg__appendPathPoint(r, r->points[0]); - // Duplicate points -> points2. + /* Duplicate points -> points2. */ nsvg__duplicatePoints(r); r->npoints = 0; cur = r->points2[0]; nsvg__appendPathPoint(r, cur); - // Figure out dash offset. + /* Figure out dash offset. */ allDashLen = 0; for (j = 0; j < shape->strokeDashCount; j++) allDashLen += shape->strokeDashArray[j]; if (shape->strokeDashCount & 1) allDashLen *= 2.0f; - // Find location inside pattern + /* Find location inside pattern */ dashOffset = fmodf(shape->strokeDashOffset, allDashLen); if (dashOffset < 0.0f) dashOffset += allDashLen; @@ -815,22 +816,22 @@ static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float float dist = sqrtf(dx*dx + dy*dy); if ((totalDist + dist) > dashLen) { - // Calculate intermediate point + /* Calculate intermediate point */ float d = (dashLen - totalDist) / dist; float x = cur.x + dx * d; float y = cur.y + dy * d; nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER); - // Stroke + /* Stroke */ if (r->npoints > 1 && dashState) { nsvg__prepareStroke(r, miterLimit, lineJoin); nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); } - // Advance dash pattern + /* Advance dash pattern */ dashState = !dashState; idash = (idash+1) % shape->strokeDashCount; dashLen = shape->strokeDashArray[idash] * scale; - // Restart + /* Restart */ cur.x = x; cur.y = y; cur.flags = NSVG_PT_CORNER; @@ -844,7 +845,7 @@ static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float j++; } } - // Stroke any leftover path + /* Stroke any leftover path */ if (r->npoints > 1 && dashState) nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); } else { @@ -871,24 +872,24 @@ static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float sta float dxdy; if (r->freelist != NULL) { - // Restore from freelist. + /* Restore from freelist. */ z = r->freelist; r->freelist = z->next; } else { - // Alloc new edge. + /* Alloc new edge. */ z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge)); if (z == NULL) return NULL; } dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); -// STBTT_assert(e->y0 <= start_point); - // round dx down to avoid going too far +/* STBTT_assert(e->y0 <= start_point); */ + /* round dx down to avoid going too far */ if (dxdy < 0) z->dx = (int)(-floorf(NSVG__FIX * -dxdy)); else z->dx = (int)floorf(NSVG__FIX * dxdy); z->x = (int)floorf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0))); -// z->x -= off_x * FIX; +/* z->x -= off_x * FIX; */ z->ey = e->y1; z->next = 0; z->dir = e->dir; @@ -910,52 +911,53 @@ static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, if (j > *xmax) *xmax = j; if (i < len && j >= 0) { if (i == j) { - // x0,x1 are the same pixel, so compute combined coverage + /* x0,x1 are the same pixel, so compute combined coverage */ scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT)); } else { - if (i >= 0) // add antialiasing for x0 + if (i >= 0) /* add antialiasing for x0 */ scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT)); else - i = -1; // clip + i = -1; /* clip */ - if (j < len) // add antialiasing for x1 + if (j < len) /* add antialiasing for x1 */ scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT)); else - j = len; // clip + j = len; /* clip */ - for (++i; i < j; ++i) // fill pixels between x0 and x1 + for (++i; i < j; ++i) /* fill pixels between x0 and x1 */ scanline[i] = (unsigned char)(scanline[i] + maxWeight); } } } -// note: this routine clips fills that extend off the edges... ideally this -// wouldn't happen, but it could happen if the truetype glyph bounding boxes -// are wrong, or if the user supplies a too-small bitmap +/* note: this routine clips fills that extend off the edges... ideally this + * wouldn't happen, but it could happen if the truetype glyph bounding boxes + * are wrong, or if the user supplies a too-small bitmap + */ static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule) { - // non-zero winding fill + /* non-zero winding fill */ int x0 = 0, w = 0; if (fillRule == NSVG_FILLRULE_NONZERO) { - // Non-zero + /* Non-zero */ while (e != NULL) { if (w == 0) { - // if we're currently at zero, we need to record the edge start point + /* if we're currently at zero, we need to record the edge start point */ x0 = e->x; w += e->dir; } else { int x1 = e->x; w += e->dir; - // if we went to zero, we need to draw + /* if we went to zero, we need to draw */ if (w == 0) nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); } e = e->next; } } else if (fillRule == NSVG_FILLRULE_EVENODD) { - // Even-odd + /* Even-odd */ while (e != NULL) { if (w == 0) { - // if we're currently at zero, we need to record the edge start point + /* if we're currently at zero, we need to record the edge start point */ x0 = e->x; w = 1; } else { int x1 = e->x; w = 0; @@ -1013,12 +1015,12 @@ static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* co int r,g,b; int a = nsvg__div255((int)cover[0] * ca); int ia = 255 - a; - // Premultiply + /* Premultiply */ r = nsvg__div255(cr * a); g = nsvg__div255(cg * a); b = nsvg__div255(cb * a); - // Blend over + /* Blend over */ r += nsvg__div255(ia * (int)dst[0]); g += nsvg__div255(ia * (int)dst[1]); b += nsvg__div255(ia * (int)dst[2]); @@ -1033,8 +1035,8 @@ static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* co dst += 4; } } else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) { - // TODO: spread modes. - // TODO: plenty of opportunities to optimize. + /* TODO: spread modes. */ + /* TODO: plenty of opportunities to optimize. */ float fx, fy, dx, gy; float* t = cache->xform; int i, cr, cg, cb, ca; @@ -1056,12 +1058,12 @@ static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* co a = nsvg__div255((int)cover[0] * ca); ia = 255 - a; - // Premultiply + /* Premultiply */ r = nsvg__div255(cr * a); g = nsvg__div255(cg * a); b = nsvg__div255(cb * a); - // Blend over + /* Blend over */ r += nsvg__div255(ia * (int)dst[0]); g += nsvg__div255(ia * (int)dst[1]); b += nsvg__div255(ia * (int)dst[2]); @@ -1077,9 +1079,9 @@ static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* co fx += dx; } } else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) { - // TODO: spread modes. - // TODO: plenty of opportunities to optimize. - // TODO: focus (fx,fy) + /* TODO: spread modes. */ + /* TODO: plenty of opportunities to optimize. */ + /* TODO: focus (fx,fy) */ float fx, fy, dx, gx, gy, gd; float* t = cache->xform; int i, cr, cg, cb, ca; @@ -1103,12 +1105,12 @@ static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* co a = nsvg__div255((int)cover[0] * ca); ia = 255 - a; - // Premultiply + /* Premultiply */ r = nsvg__div255(cr * a); g = nsvg__div255(cg * a); b = nsvg__div255(cb * a); - // Blend over + /* Blend over */ r += nsvg__div255(ia * (int)dst[0]); g += nsvg__div255(ia * (int)dst[1]); b += nsvg__div255(ia * (int)dst[2]); @@ -1131,7 +1133,7 @@ static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, fl NSVGactiveEdge *active = NULL; int y, s; int e = 0; - int maxWeight = (255 / NSVG__SUBSAMPLES); // weight per vertical scanline + int maxWeight = (255 / NSVG__SUBSAMPLES); /* weight per vertical scanline */ int xmin, xmax; for (y = 0; y < r->height; y++) { @@ -1139,25 +1141,25 @@ static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, fl xmin = r->width; xmax = 0; for (s = 0; s < NSVG__SUBSAMPLES; ++s) { - // find center of pixel for this scanline + /* find center of pixel for this scanline */ float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f; NSVGactiveEdge **step = &active; - // update all active edges; - // remove all active edges that terminate before the center of this scanline + /* update all active edges; */ + /* remove all active edges that terminate before the center of this scanline */ while (*step) { NSVGactiveEdge *z = *step; if (z->ey <= scany) { - *step = z->next; // delete from list -// NSVG__assert(z->valid); + *step = z->next; /* delete from list */ +/* NSVG__assert(z->valid); */ nsvg__freeActive(r, z); } else { - z->x += z->dx; // advance to position for current scanline - step = &((*step)->next); // advance through list + z->x += z->dx; /* advance to position for current scanline */ + step = &((*step)->next); /* advance through list */ } } - // resort the list if needed + /* resort the list if needed */ for (;;) { int changed = 0; step = &active; @@ -1175,24 +1177,24 @@ static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, fl if (!changed) break; } - // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + /* insert all edges that start before the center of this scanline -- omit ones that also end on this scanline */ while (e < r->nedges && r->edges[e].y0 <= scany) { if (r->edges[e].y1 > scany) { NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany); if (z == NULL) break; - // find insertion point + /* find insertion point */ if (active == NULL) { active = z; } else if (z->x < active->x) { - // insert at front + /* insert at front */ z->next = active; active = z; } else { - // find thing to insert AFTER + /* find thing to insert AFTER */ NSVGactiveEdge* p = active; while (p->next && p->next->x < z->x) p = p->next; - // at this point, p->next->x is NOT < z->x + /* at this point, p->next->x is NOT < z->x */ z->next = p->next; p->next = z; } @@ -1200,11 +1202,11 @@ static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, fl e++; } - // now process all active edges in non-zero fashion + /* now process all active edges in non-zero fashion */ if (active != NULL) nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule); } - // Blit + /* Blit */ if (xmin < 0) xmin = 0; if (xmax > r->width-1) xmax = r->width-1; if (xmin <= xmax) { @@ -1218,7 +1220,7 @@ static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int str { int x,y; - // Unpremultiply + /* Unpremultiply */ for (y = 0; y < h; y++) { unsigned char *row = &image[y*stride]; for (x = 0; x < w; x++) { @@ -1232,7 +1234,7 @@ static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int str } } - // Defringe + /* Defringe */ for (y = 0; y < h; y++) { unsigned char *row = &image[y*stride]; for (x = 0; x < w; x++) { @@ -1411,7 +1413,7 @@ void nsvgRasterize(NSVGrasterizer* r, nsvg__flattenShape(r, shape, scale); - // Scale and translate edges + /* Scale and translate edges */ for (i = 0; i < r->nedges; i++) { e = &r->edges[i]; e->x0 = tx + e->x0; @@ -1420,10 +1422,10 @@ void nsvgRasterize(NSVGrasterizer* r, e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; } - // Rasterize edges + /* Rasterize edges */ qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); - // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + /* now, traverse the scanlines and find the intersections on each scanline, use non-zero rule */ nsvg__initPaint(&cache, &shape->fill, shape->opacity); nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, shape->fillRule); @@ -1435,9 +1437,9 @@ void nsvgRasterize(NSVGrasterizer* r, nsvg__flattenShapeStroke(r, shape, scale); -// dumpEdges(r, "edge.svg"); +/* dumpEdges(r, "edge.svg"); */ - // Scale and translate edges + /* Scale and translate edges */ for (i = 0; i < r->nedges; i++) { e = &r->edges[i]; e->x0 = tx + e->x0; @@ -1446,10 +1448,10 @@ void nsvgRasterize(NSVGrasterizer* r, e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; } - // Rasterize edges + /* Rasterize edges */ qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); - // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + /* now, traverse the scanlines and find the intersections on each scanline, use non-zero rule */ nsvg__initPaint(&cache, &shape->stroke, shape->opacity); nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, NSVG_FILLRULE_NONZERO); |