nanosvgrast.h 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460
  1. /*
  2. * Copyright (c) 2013-14 Mikko Mononen [email protected]
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. *
  20. * The polygon rasterization is heavily based on stb_truetype rasterizer
  21. * by Sean Barrett - http://nothings.org/
  22. *
  23. */
  24. #ifndef NANOSVGRAST_H
  25. #define NANOSVGRAST_H
  26. #include "nanosvg.h"
  27. #ifndef NANOSVGRAST_CPLUSPLUS
  28. #ifdef __cplusplus
  29. extern "C" {
  30. #endif
  31. #endif
  32. typedef struct NSVGrasterizer NSVGrasterizer;
  33. /* Example Usage:
  34. // Load SVG
  35. NSVGimage* image;
  36. image = nsvgParseFromFile("test.svg", "px", 96);
  37. // Create rasterizer (can be used to render multiple images).
  38. struct NSVGrasterizer* rast = nsvgCreateRasterizer();
  39. // Allocate memory for image
  40. unsigned char* img = malloc(w*h*4);
  41. // Rasterize
  42. nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4);
  43. */
  44. // Allocated rasterizer context.
  45. NSVGrasterizer* nsvgCreateRasterizer(void);
  46. // Rasterizes SVG image, returns RGBA image (non-premultiplied alpha)
  47. // r - pointer to rasterizer context
  48. // image - pointer to image to rasterize
  49. // tx,ty - image offset (applied after scaling)
  50. // scale - image scale
  51. // dst - pointer to destination image data, 4 bytes per pixel (RGBA)
  52. // w - width of the image to render
  53. // h - height of the image to render
  54. // stride - number of bytes per scaleline in the destination buffer
  55. void nsvgRasterize(NSVGrasterizer* r,
  56. NSVGimage* image, float tx, float ty, float scale,
  57. unsigned char* dst, int w, int h, int stride);
  58. // Deletes rasterizer context.
  59. void nsvgDeleteRasterizer(NSVGrasterizer*);
  60. #ifndef NANOSVGRAST_CPLUSPLUS
  61. #ifdef __cplusplus
  62. }
  63. #endif
  64. #endif
  65. #ifdef NANOSVGRAST_IMPLEMENTATION
  66. #include <math.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #define NSVG__SUBSAMPLES 5
  70. #define NSVG__FIXSHIFT 10
  71. #define NSVG__FIX (1 << NSVG__FIXSHIFT)
  72. #define NSVG__FIXMASK (NSVG__FIX-1)
  73. #define NSVG__MEMPAGE_SIZE 1024
  74. typedef struct NSVGedge {
  75. float x0,y0, x1,y1;
  76. int dir;
  77. struct NSVGedge* next;
  78. } NSVGedge;
  79. typedef struct NSVGpoint {
  80. float x, y;
  81. float dx, dy;
  82. float len;
  83. float dmx, dmy;
  84. unsigned char flags;
  85. } NSVGpoint;
  86. typedef struct NSVGactiveEdge {
  87. int x,dx;
  88. float ey;
  89. int dir;
  90. struct NSVGactiveEdge *next;
  91. } NSVGactiveEdge;
  92. typedef struct NSVGmemPage {
  93. unsigned char mem[NSVG__MEMPAGE_SIZE];
  94. int size;
  95. struct NSVGmemPage* next;
  96. } NSVGmemPage;
  97. typedef struct NSVGcachedPaint {
  98. signed char type;
  99. char spread;
  100. float xform[6];
  101. unsigned int colors[256];
  102. } NSVGcachedPaint;
  103. struct NSVGrasterizer
  104. {
  105. float px, py;
  106. float tessTol;
  107. float distTol;
  108. NSVGedge* edges;
  109. int nedges;
  110. int cedges;
  111. NSVGpoint* points;
  112. int npoints;
  113. int cpoints;
  114. NSVGpoint* points2;
  115. int npoints2;
  116. int cpoints2;
  117. NSVGactiveEdge* freelist;
  118. NSVGmemPage* pages;
  119. NSVGmemPage* curpage;
  120. unsigned char* scanline;
  121. int cscanline;
  122. unsigned char* bitmap;
  123. int width, height, stride;
  124. };
  125. NSVGrasterizer* nsvgCreateRasterizer(void)
  126. {
  127. NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer));
  128. if (r == NULL) goto error;
  129. memset(r, 0, sizeof(NSVGrasterizer));
  130. r->tessTol = 0.25f;
  131. r->distTol = 0.01f;
  132. return r;
  133. error:
  134. nsvgDeleteRasterizer(r);
  135. return NULL;
  136. }
  137. void nsvgDeleteRasterizer(NSVGrasterizer* r)
  138. {
  139. NSVGmemPage* p;
  140. if (r == NULL) return;
  141. p = r->pages;
  142. while (p != NULL) {
  143. NSVGmemPage* next = p->next;
  144. free(p);
  145. p = next;
  146. }
  147. if (r->edges) free(r->edges);
  148. if (r->points) free(r->points);
  149. if (r->points2) free(r->points2);
  150. if (r->scanline) free(r->scanline);
  151. free(r);
  152. }
  153. static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur)
  154. {
  155. NSVGmemPage *newp;
  156. // If using existing chain, return the next page in chain
  157. if (cur != NULL && cur->next != NULL) {
  158. return cur->next;
  159. }
  160. // Alloc new page
  161. newp = (NSVGmemPage*)malloc(sizeof(NSVGmemPage));
  162. if (newp == NULL) return NULL;
  163. memset(newp, 0, sizeof(NSVGmemPage));
  164. // Add to linked list
  165. if (cur != NULL)
  166. cur->next = newp;
  167. else
  168. r->pages = newp;
  169. return newp;
  170. }
  171. static void nsvg__resetPool(NSVGrasterizer* r)
  172. {
  173. NSVGmemPage* p = r->pages;
  174. while (p != NULL) {
  175. p->size = 0;
  176. p = p->next;
  177. }
  178. r->curpage = r->pages;
  179. }
  180. static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size)
  181. {
  182. unsigned char* buf;
  183. if (size > NSVG__MEMPAGE_SIZE) return NULL;
  184. if (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) {
  185. r->curpage = nsvg__nextPage(r, r->curpage);
  186. }
  187. buf = &r->curpage->mem[r->curpage->size];
  188. r->curpage->size += size;
  189. return buf;
  190. }
  191. static int nsvg__ptEquals(float x1, float y1, float x2, float y2, float tol)
  192. {
  193. float dx = x2 - x1;
  194. float dy = y2 - y1;
  195. return dx*dx + dy*dy < tol*tol;
  196. }
  197. static void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags)
  198. {
  199. NSVGpoint* pt;
  200. if (r->npoints > 0) {
  201. pt = &r->points[r->npoints-1];
  202. if (nsvg__ptEquals(pt->x,pt->y, x,y, r->distTol)) {
  203. pt->flags = (unsigned char)(pt->flags | flags);
  204. return;
  205. }
  206. }
  207. if (r->npoints+1 > r->cpoints) {
  208. r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
  209. r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints);
  210. if (r->points == NULL) return;
  211. }
  212. pt = &r->points[r->npoints];
  213. pt->x = x;
  214. pt->y = y;
  215. pt->flags = (unsigned char)flags;
  216. r->npoints++;
  217. }
  218. static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt)
  219. {
  220. if (r->npoints+1 > r->cpoints) {
  221. r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
  222. r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints);
  223. if (r->points == NULL) return;
  224. }
  225. r->points[r->npoints] = pt;
  226. r->npoints++;
  227. }
  228. static void nsvg__duplicatePoints(NSVGrasterizer* r)
  229. {
  230. if (r->npoints > r->cpoints2) {
  231. r->cpoints2 = r->npoints;
  232. r->points2 = (NSVGpoint*)realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2);
  233. if (r->points2 == NULL) return;
  234. }
  235. memcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints);
  236. r->npoints2 = r->npoints;
  237. }
  238. static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1)
  239. {
  240. NSVGedge* e;
  241. // Skip horizontal edges
  242. if (y0 == y1)
  243. return;
  244. if (r->nedges+1 > r->cedges) {
  245. r->cedges = r->cedges > 0 ? r->cedges * 2 : 64;
  246. r->edges = (NSVGedge*)realloc(r->edges, sizeof(NSVGedge) * r->cedges);
  247. if (r->edges == NULL) return;
  248. }
  249. e = &r->edges[r->nedges];
  250. r->nedges++;
  251. if (y0 < y1) {
  252. e->x0 = x0;
  253. e->y0 = y0;
  254. e->x1 = x1;
  255. e->y1 = y1;
  256. e->dir = 1;
  257. } else {
  258. e->x0 = x1;
  259. e->y0 = y1;
  260. e->x1 = x0;
  261. e->y1 = y0;
  262. e->dir = -1;
  263. }
  264. }
  265. static float nsvg__normalize(float *x, float* y)
  266. {
  267. float d = sqrtf((*x)*(*x) + (*y)*(*y));
  268. if (d > 1e-6f) {
  269. float id = 1.0f / d;
  270. *x *= id;
  271. *y *= id;
  272. }
  273. return d;
  274. }
  275. static float nsvg__absf(float x) { return x < 0 ? -x : x; }
  276. static float nsvg__roundf(float x) { return (x >= 0) ? floorf(x + 0.5) : ceilf(x - 0.5); }
  277. static void nsvg__flattenCubicBez(NSVGrasterizer* r,
  278. float x1, float y1, float x2, float y2,
  279. float x3, float y3, float x4, float y4,
  280. int level, int type)
  281. {
  282. float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234;
  283. float dx,dy,d2,d3;
  284. if (level > 10) return;
  285. x12 = (x1+x2)*0.5f;
  286. y12 = (y1+y2)*0.5f;
  287. x23 = (x2+x3)*0.5f;
  288. y23 = (y2+y3)*0.5f;
  289. x34 = (x3+x4)*0.5f;
  290. y34 = (y3+y4)*0.5f;
  291. x123 = (x12+x23)*0.5f;
  292. y123 = (y12+y23)*0.5f;
  293. dx = x4 - x1;
  294. dy = y4 - y1;
  295. d2 = nsvg__absf((x2 - x4) * dy - (y2 - y4) * dx);
  296. d3 = nsvg__absf((x3 - x4) * dy - (y3 - y4) * dx);
  297. if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) {
  298. nsvg__addPathPoint(r, x4, y4, type);
  299. return;
  300. }
  301. x234 = (x23+x34)*0.5f;
  302. y234 = (y23+y34)*0.5f;
  303. x1234 = (x123+x234)*0.5f;
  304. y1234 = (y123+y234)*0.5f;
  305. nsvg__flattenCubicBez(r, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0);
  306. nsvg__flattenCubicBez(r, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type);
  307. }
  308. static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale)
  309. {
  310. int i, j;
  311. NSVGpath* path;
  312. for (path = shape->paths; path != NULL; path = path->next) {
  313. r->npoints = 0;
  314. // Flatten path
  315. nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0);
  316. for (i = 0; i < path->npts-1; i += 3) {
  317. float* p = &path->pts[i*2];
  318. 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);
  319. }
  320. // Close path
  321. nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0);
  322. // Build edges
  323. for (i = 0, j = r->npoints-1; i < r->npoints; j = i++)
  324. nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y);
  325. }
  326. }
  327. enum NSVGpointFlags
  328. {
  329. NSVG_PT_CORNER = 0x01,
  330. NSVG_PT_BEVEL = 0x02,
  331. NSVG_PT_LEFT = 0x04
  332. };
  333. static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
  334. {
  335. float w = lineWidth * 0.5f;
  336. float dx = p1->x - p0->x;
  337. float dy = p1->y - p0->y;
  338. float len = nsvg__normalize(&dx, &dy);
  339. float px = p0->x + dx*len*0.5f, py = p0->y + dy*len*0.5f;
  340. float dlx = dy, dly = -dx;
  341. float lx = px - dlx*w, ly = py - dly*w;
  342. float rx = px + dlx*w, ry = py + dly*w;
  343. left->x = lx; left->y = ly;
  344. right->x = rx; right->y = ry;
  345. }
  346. static void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)
  347. {
  348. float w = lineWidth * 0.5f;
  349. float px = p->x, py = p->y;
  350. float dlx = dy, dly = -dx;
  351. float lx = px - dlx*w, ly = py - dly*w;
  352. float rx = px + dlx*w, ry = py + dly*w;
  353. nsvg__addEdge(r, lx, ly, rx, ry);
  354. if (connect) {
  355. nsvg__addEdge(r, left->x, left->y, lx, ly);
  356. nsvg__addEdge(r, rx, ry, right->x, right->y);
  357. }
  358. left->x = lx; left->y = ly;
  359. right->x = rx; right->y = ry;
  360. }
  361. static void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)
  362. {
  363. float w = lineWidth * 0.5f;
  364. float px = p->x - dx*w, py = p->y - dy*w;
  365. float dlx = dy, dly = -dx;
  366. float lx = px - dlx*w, ly = py - dly*w;
  367. float rx = px + dlx*w, ry = py + dly*w;
  368. nsvg__addEdge(r, lx, ly, rx, ry);
  369. if (connect) {
  370. nsvg__addEdge(r, left->x, left->y, lx, ly);
  371. nsvg__addEdge(r, rx, ry, right->x, right->y);
  372. }
  373. left->x = lx; left->y = ly;
  374. right->x = rx; right->y = ry;
  375. }
  376. #ifndef NSVG_PI
  377. #define NSVG_PI (3.14159265358979323846264338327f)
  378. #endif
  379. static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect)
  380. {
  381. int i;
  382. float w = lineWidth * 0.5f;
  383. float px = p->x, py = p->y;
  384. float dlx = dy, dly = -dx;
  385. float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0;
  386. for (i = 0; i < ncap; i++) {
  387. float a = (float)i/(float)(ncap-1)*NSVG_PI;
  388. float ax = cosf(a) * w, ay = sinf(a) * w;
  389. float x = px - dlx*ax - dx*ay;
  390. float y = py - dly*ax - dy*ay;
  391. if (i > 0)
  392. nsvg__addEdge(r, prevx, prevy, x, y);
  393. prevx = x;
  394. prevy = y;
  395. if (i == 0) {
  396. lx = x; ly = y;
  397. } else if (i == ncap-1) {
  398. rx = x; ry = y;
  399. }
  400. }
  401. if (connect) {
  402. nsvg__addEdge(r, left->x, left->y, lx, ly);
  403. nsvg__addEdge(r, rx, ry, right->x, right->y);
  404. }
  405. left->x = lx; left->y = ly;
  406. right->x = rx; right->y = ry;
  407. }
  408. static void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
  409. {
  410. float w = lineWidth * 0.5f;
  411. float dlx0 = p0->dy, dly0 = -p0->dx;
  412. float dlx1 = p1->dy, dly1 = -p1->dx;
  413. float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w);
  414. float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w);
  415. float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w);
  416. float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w);
  417. nsvg__addEdge(r, lx0, ly0, left->x, left->y);
  418. nsvg__addEdge(r, lx1, ly1, lx0, ly0);
  419. nsvg__addEdge(r, right->x, right->y, rx0, ry0);
  420. nsvg__addEdge(r, rx0, ry0, rx1, ry1);
  421. left->x = lx1; left->y = ly1;
  422. right->x = rx1; right->y = ry1;
  423. }
  424. static void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
  425. {
  426. float w = lineWidth * 0.5f;
  427. float dlx0 = p0->dy, dly0 = -p0->dx;
  428. float dlx1 = p1->dy, dly1 = -p1->dx;
  429. float lx0, rx0, lx1, rx1;
  430. float ly0, ry0, ly1, ry1;
  431. if (p1->flags & NSVG_PT_LEFT) {
  432. lx0 = lx1 = p1->x - p1->dmx * w;
  433. ly0 = ly1 = p1->y - p1->dmy * w;
  434. nsvg__addEdge(r, lx1, ly1, left->x, left->y);
  435. rx0 = p1->x + (dlx0 * w);
  436. ry0 = p1->y + (dly0 * w);
  437. rx1 = p1->x + (dlx1 * w);
  438. ry1 = p1->y + (dly1 * w);
  439. nsvg__addEdge(r, right->x, right->y, rx0, ry0);
  440. nsvg__addEdge(r, rx0, ry0, rx1, ry1);
  441. } else {
  442. lx0 = p1->x - (dlx0 * w);
  443. ly0 = p1->y - (dly0 * w);
  444. lx1 = p1->x - (dlx1 * w);
  445. ly1 = p1->y - (dly1 * w);
  446. nsvg__addEdge(r, lx0, ly0, left->x, left->y);
  447. nsvg__addEdge(r, lx1, ly1, lx0, ly0);
  448. rx0 = rx1 = p1->x + p1->dmx * w;
  449. ry0 = ry1 = p1->y + p1->dmy * w;
  450. nsvg__addEdge(r, right->x, right->y, rx1, ry1);
  451. }
  452. left->x = lx1; left->y = ly1;
  453. right->x = rx1; right->y = ry1;
  454. }
  455. static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap)
  456. {
  457. int i, n;
  458. float w = lineWidth * 0.5f;
  459. float dlx0 = p0->dy, dly0 = -p0->dx;
  460. float dlx1 = p1->dy, dly1 = -p1->dx;
  461. float a0 = atan2f(dly0, dlx0);
  462. float a1 = atan2f(dly1, dlx1);
  463. float da = a1 - a0;
  464. float lx, ly, rx, ry;
  465. if (da < NSVG_PI) da += NSVG_PI*2;
  466. if (da > NSVG_PI) da -= NSVG_PI*2;
  467. n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap);
  468. if (n < 2) n = 2;
  469. if (n > ncap) n = ncap;
  470. lx = left->x;
  471. ly = left->y;
  472. rx = right->x;
  473. ry = right->y;
  474. for (i = 0; i < n; i++) {
  475. float u = (float)i/(float)(n-1);
  476. float a = a0 + u*da;
  477. float ax = cosf(a) * w, ay = sinf(a) * w;
  478. float lx1 = p1->x - ax, ly1 = p1->y - ay;
  479. float rx1 = p1->x + ax, ry1 = p1->y + ay;
  480. nsvg__addEdge(r, lx1, ly1, lx, ly);
  481. nsvg__addEdge(r, rx, ry, rx1, ry1);
  482. lx = lx1; ly = ly1;
  483. rx = rx1; ry = ry1;
  484. }
  485. left->x = lx; left->y = ly;
  486. right->x = rx; right->y = ry;
  487. }
  488. static void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth)
  489. {
  490. float w = lineWidth * 0.5f;
  491. float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w);
  492. float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w);
  493. nsvg__addEdge(r, lx, ly, left->x, left->y);
  494. nsvg__addEdge(r, right->x, right->y, rx, ry);
  495. left->x = lx; left->y = ly;
  496. right->x = rx; right->y = ry;
  497. }
  498. static int nsvg__curveDivs(float r, float arc, float tol)
  499. {
  500. float da = acosf(r / (r + tol)) * 2.0f;
  501. int divs = (int)ceilf(arc / da);
  502. if (divs < 2) divs = 2;
  503. return divs;
  504. }
  505. static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth)
  506. {
  507. int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol); // Calculate divisions per half circle.
  508. 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};
  509. NSVGpoint* p0, *p1;
  510. int j, s, e;
  511. // Build stroke edges
  512. if (closed) {
  513. // Looping
  514. p0 = &points[npoints-1];
  515. p1 = &points[0];
  516. s = 0;
  517. e = npoints;
  518. } else {
  519. // Add cap
  520. p0 = &points[0];
  521. p1 = &points[1];
  522. s = 1;
  523. e = npoints-1;
  524. }
  525. if (closed) {
  526. nsvg__initClosed(&left, &right, p0, p1, lineWidth);
  527. firstLeft = left;
  528. firstRight = right;
  529. } else {
  530. // Add cap
  531. float dx = p1->x - p0->x;
  532. float dy = p1->y - p0->y;
  533. nsvg__normalize(&dx, &dy);
  534. if (lineCap == NSVG_CAP_BUTT)
  535. nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
  536. else if (lineCap == NSVG_CAP_SQUARE)
  537. nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
  538. else if (lineCap == NSVG_CAP_ROUND)
  539. nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0);
  540. }
  541. for (j = s; j < e; ++j) {
  542. if (p1->flags & NSVG_PT_CORNER) {
  543. if (lineJoin == NSVG_JOIN_ROUND)
  544. nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap);
  545. else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL))
  546. nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth);
  547. else
  548. nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth);
  549. } else {
  550. nsvg__straightJoin(r, &left, &right, p1, lineWidth);
  551. }
  552. p0 = p1++;
  553. }
  554. if (closed) {
  555. // Loop it
  556. nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y);
  557. nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y);
  558. } else {
  559. // Add cap
  560. float dx = p1->x - p0->x;
  561. float dy = p1->y - p0->y;
  562. nsvg__normalize(&dx, &dy);
  563. if (lineCap == NSVG_CAP_BUTT)
  564. nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
  565. else if (lineCap == NSVG_CAP_SQUARE)
  566. nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
  567. else if (lineCap == NSVG_CAP_ROUND)
  568. nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1);
  569. }
  570. }
  571. static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin)
  572. {
  573. int i, j;
  574. NSVGpoint* p0, *p1;
  575. p0 = &r->points[r->npoints-1];
  576. p1 = &r->points[0];
  577. for (i = 0; i < r->npoints; i++) {
  578. // Calculate segment direction and length
  579. p0->dx = p1->x - p0->x;
  580. p0->dy = p1->y - p0->y;
  581. p0->len = nsvg__normalize(&p0->dx, &p0->dy);
  582. // Advance
  583. p0 = p1++;
  584. }
  585. // calculate joins
  586. p0 = &r->points[r->npoints-1];
  587. p1 = &r->points[0];
  588. for (j = 0; j < r->npoints; j++) {
  589. float dlx0, dly0, dlx1, dly1, dmr2, cross;
  590. dlx0 = p0->dy;
  591. dly0 = -p0->dx;
  592. dlx1 = p1->dy;
  593. dly1 = -p1->dx;
  594. // Calculate extrusions
  595. p1->dmx = (dlx0 + dlx1) * 0.5f;
  596. p1->dmy = (dly0 + dly1) * 0.5f;
  597. dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy;
  598. if (dmr2 > 0.000001f) {
  599. float s2 = 1.0f / dmr2;
  600. if (s2 > 600.0f) {
  601. s2 = 600.0f;
  602. }
  603. p1->dmx *= s2;
  604. p1->dmy *= s2;
  605. }
  606. // Clear flags, but keep the corner.
  607. p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0;
  608. // Keep track of left turns.
  609. cross = p1->dx * p0->dy - p0->dx * p1->dy;
  610. if (cross > 0.0f)
  611. p1->flags |= NSVG_PT_LEFT;
  612. // Check to see if the corner needs to be beveled.
  613. if (p1->flags & NSVG_PT_CORNER) {
  614. if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) {
  615. p1->flags |= NSVG_PT_BEVEL;
  616. }
  617. }
  618. p0 = p1++;
  619. }
  620. }
  621. static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float scale)
  622. {
  623. int i, j, closed;
  624. NSVGpath* path;
  625. NSVGpoint* p0, *p1;
  626. float miterLimit = shape->miterLimit;
  627. int lineJoin = shape->strokeLineJoin;
  628. int lineCap = shape->strokeLineCap;
  629. float lineWidth = shape->strokeWidth * scale;
  630. for (path = shape->paths; path != NULL; path = path->next) {
  631. // Flatten path
  632. r->npoints = 0;
  633. nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, NSVG_PT_CORNER);
  634. for (i = 0; i < path->npts-1; i += 3) {
  635. float* p = &path->pts[i*2];
  636. 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);
  637. }
  638. if (r->npoints < 2)
  639. continue;
  640. closed = path->closed;
  641. // If the first and last points are the same, remove the last, mark as closed path.
  642. p0 = &r->points[r->npoints-1];
  643. p1 = &r->points[0];
  644. if (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) {
  645. r->npoints--;
  646. p0 = &r->points[r->npoints-1];
  647. closed = 1;
  648. }
  649. if (shape->strokeDashCount > 0) {
  650. int idash = 0, dashState = 1;
  651. float totalDist = 0, dashLen, allDashLen, dashOffset;
  652. NSVGpoint cur;
  653. if (closed)
  654. nsvg__appendPathPoint(r, r->points[0]);
  655. // Duplicate points -> points2.
  656. nsvg__duplicatePoints(r);
  657. r->npoints = 0;
  658. cur = r->points2[0];
  659. nsvg__appendPathPoint(r, cur);
  660. // Figure out dash offset.
  661. allDashLen = 0;
  662. for (j = 0; j < shape->strokeDashCount; j++)
  663. allDashLen += shape->strokeDashArray[j];
  664. if (shape->strokeDashCount & 1)
  665. allDashLen *= 2.0f;
  666. // Find location inside pattern
  667. dashOffset = fmodf(shape->strokeDashOffset, allDashLen);
  668. if (dashOffset < 0.0f)
  669. dashOffset += allDashLen;
  670. while (dashOffset > shape->strokeDashArray[idash]) {
  671. dashOffset -= shape->strokeDashArray[idash];
  672. idash = (idash + 1) % shape->strokeDashCount;
  673. }
  674. dashLen = (shape->strokeDashArray[idash] - dashOffset) * scale;
  675. for (j = 1; j < r->npoints2; ) {
  676. float dx = r->points2[j].x - cur.x;
  677. float dy = r->points2[j].y - cur.y;
  678. float dist = sqrtf(dx*dx + dy*dy);
  679. if ((totalDist + dist) > dashLen) {
  680. // Calculate intermediate point
  681. float d = (dashLen - totalDist) / dist;
  682. float x = cur.x + dx * d;
  683. float y = cur.y + dy * d;
  684. nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER);
  685. // Stroke
  686. if (r->npoints > 1 && dashState) {
  687. nsvg__prepareStroke(r, miterLimit, lineJoin);
  688. nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
  689. }
  690. // Advance dash pattern
  691. dashState = !dashState;
  692. idash = (idash+1) % shape->strokeDashCount;
  693. dashLen = shape->strokeDashArray[idash] * scale;
  694. // Restart
  695. cur.x = x;
  696. cur.y = y;
  697. cur.flags = NSVG_PT_CORNER;
  698. totalDist = 0.0f;
  699. r->npoints = 0;
  700. nsvg__appendPathPoint(r, cur);
  701. } else {
  702. totalDist += dist;
  703. cur = r->points2[j];
  704. nsvg__appendPathPoint(r, cur);
  705. j++;
  706. }
  707. }
  708. // Stroke any leftover path
  709. if (r->npoints > 1 && dashState)
  710. nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
  711. } else {
  712. nsvg__prepareStroke(r, miterLimit, lineJoin);
  713. nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth);
  714. }
  715. }
  716. }
  717. static int nsvg__cmpEdge(const void *p, const void *q)
  718. {
  719. const NSVGedge* a = (const NSVGedge*)p;
  720. const NSVGedge* b = (const NSVGedge*)q;
  721. if (a->y0 < b->y0) return -1;
  722. if (a->y0 > b->y0) return 1;
  723. return 0;
  724. }
  725. static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint)
  726. {
  727. NSVGactiveEdge* z;
  728. if (r->freelist != NULL) {
  729. // Restore from freelist.
  730. z = r->freelist;
  731. r->freelist = z->next;
  732. } else {
  733. // Alloc new edge.
  734. z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge));
  735. if (z == NULL) return NULL;
  736. }
  737. float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
  738. // STBTT_assert(e->y0 <= start_point);
  739. // round dx down to avoid going too far
  740. if (dxdy < 0)
  741. z->dx = (int)(-nsvg__roundf(NSVG__FIX * -dxdy));
  742. else
  743. z->dx = (int)nsvg__roundf(NSVG__FIX * dxdy);
  744. z->x = (int)nsvg__roundf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));
  745. // z->x -= off_x * FIX;
  746. z->ey = e->y1;
  747. z->next = 0;
  748. z->dir = e->dir;
  749. return z;
  750. }
  751. static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z)
  752. {
  753. z->next = r->freelist;
  754. r->freelist = z;
  755. }
  756. static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax)
  757. {
  758. int i = x0 >> NSVG__FIXSHIFT;
  759. int j = x1 >> NSVG__FIXSHIFT;
  760. if (i < *xmin) *xmin = i;
  761. if (j > *xmax) *xmax = j;
  762. if (i < len && j >= 0) {
  763. if (i == j) {
  764. // x0,x1 are the same pixel, so compute combined coverage
  765. scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT));
  766. } else {
  767. if (i >= 0) // add antialiasing for x0
  768. scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT));
  769. else
  770. i = -1; // clip
  771. if (j < len) // add antialiasing for x1
  772. scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT));
  773. else
  774. j = len; // clip
  775. for (++i; i < j; ++i) // fill pixels between x0 and x1
  776. scanline[i] = (unsigned char)(scanline[i] + maxWeight);
  777. }
  778. }
  779. }
  780. // note: this routine clips fills that extend off the edges... ideally this
  781. // wouldn't happen, but it could happen if the truetype glyph bounding boxes
  782. // are wrong, or if the user supplies a too-small bitmap
  783. static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule)
  784. {
  785. // non-zero winding fill
  786. int x0 = 0, w = 0;
  787. if (fillRule == NSVG_FILLRULE_NONZERO) {
  788. // Non-zero
  789. while (e != NULL) {
  790. if (w == 0) {
  791. // if we're currently at zero, we need to record the edge start point
  792. x0 = e->x; w += e->dir;
  793. } else {
  794. int x1 = e->x; w += e->dir;
  795. // if we went to zero, we need to draw
  796. if (w == 0)
  797. nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
  798. }
  799. e = e->next;
  800. }
  801. } else if (fillRule == NSVG_FILLRULE_EVENODD) {
  802. // Even-odd
  803. while (e != NULL) {
  804. if (w == 0) {
  805. // if we're currently at zero, we need to record the edge start point
  806. x0 = e->x; w = 1;
  807. } else {
  808. int x1 = e->x; w = 0;
  809. nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
  810. }
  811. e = e->next;
  812. }
  813. }
  814. }
  815. static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); }
  816. static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
  817. {
  818. return ((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24);
  819. }
  820. static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u)
  821. {
  822. int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
  823. int r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8;
  824. int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8;
  825. int b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8;
  826. int a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8;
  827. return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
  828. }
  829. static unsigned int nsvg__applyOpacity(unsigned int c, float u)
  830. {
  831. int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
  832. int r = (c) & 0xff;
  833. int g = (c>>8) & 0xff;
  834. int b = (c>>16) & 0xff;
  835. int a = (((c>>24) & 0xff)*iu) >> 8;
  836. return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
  837. }
  838. static inline int nsvg__div255(int x)
  839. {
  840. return ((x+1) * 257) >> 16;
  841. }
  842. static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y,
  843. float tx, float ty, float scale, NSVGcachedPaint* cache)
  844. {
  845. if (cache->type == NSVG_PAINT_COLOR) {
  846. int i, cr, cg, cb, ca;
  847. cr = cache->colors[0] & 0xff;
  848. cg = (cache->colors[0] >> 8) & 0xff;
  849. cb = (cache->colors[0] >> 16) & 0xff;
  850. ca = (cache->colors[0] >> 24) & 0xff;
  851. for (i = 0; i < count; i++) {
  852. int r,g,b;
  853. int a = nsvg__div255((int)cover[0] * ca);
  854. int ia = 255 - a;
  855. // Premultiply
  856. r = nsvg__div255(cr * a);
  857. g = nsvg__div255(cg * a);
  858. b = nsvg__div255(cb * a);
  859. // Blend over
  860. r += nsvg__div255(ia * (int)dst[0]);
  861. g += nsvg__div255(ia * (int)dst[1]);
  862. b += nsvg__div255(ia * (int)dst[2]);
  863. a += nsvg__div255(ia * (int)dst[3]);
  864. dst[0] = (unsigned char)r;
  865. dst[1] = (unsigned char)g;
  866. dst[2] = (unsigned char)b;
  867. dst[3] = (unsigned char)a;
  868. cover++;
  869. dst += 4;
  870. }
  871. } else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) {
  872. // TODO: spread modes.
  873. // TODO: plenty of opportunities to optimize.
  874. float fx, fy, dx, gy;
  875. float* t = cache->xform;
  876. int i, cr, cg, cb, ca;
  877. unsigned int c;
  878. fx = ((float)x - tx) / scale;
  879. fy = ((float)y - ty) / scale;
  880. dx = 1.0f / scale;
  881. for (i = 0; i < count; i++) {
  882. int r,g,b,a,ia;
  883. gy = fx*t[1] + fy*t[3] + t[5];
  884. c = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)];
  885. cr = (c) & 0xff;
  886. cg = (c >> 8) & 0xff;
  887. cb = (c >> 16) & 0xff;
  888. ca = (c >> 24) & 0xff;
  889. a = nsvg__div255((int)cover[0] * ca);
  890. ia = 255 - a;
  891. // Premultiply
  892. r = nsvg__div255(cr * a);
  893. g = nsvg__div255(cg * a);
  894. b = nsvg__div255(cb * a);
  895. // Blend over
  896. r += nsvg__div255(ia * (int)dst[0]);
  897. g += nsvg__div255(ia * (int)dst[1]);
  898. b += nsvg__div255(ia * (int)dst[2]);
  899. a += nsvg__div255(ia * (int)dst[3]);
  900. dst[0] = (unsigned char)r;
  901. dst[1] = (unsigned char)g;
  902. dst[2] = (unsigned char)b;
  903. dst[3] = (unsigned char)a;
  904. cover++;
  905. dst += 4;
  906. fx += dx;
  907. }
  908. } else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) {
  909. // TODO: spread modes.
  910. // TODO: plenty of opportunities to optimize.
  911. // TODO: focus (fx,fy)
  912. float fx, fy, dx, gx, gy, gd;
  913. float* t = cache->xform;
  914. int i, cr, cg, cb, ca;
  915. unsigned int c;
  916. fx = ((float)x - tx) / scale;
  917. fy = ((float)y - ty) / scale;
  918. dx = 1.0f / scale;
  919. for (i = 0; i < count; i++) {
  920. int r,g,b,a,ia;
  921. gx = fx*t[0] + fy*t[2] + t[4];
  922. gy = fx*t[1] + fy*t[3] + t[5];
  923. gd = sqrtf(gx*gx + gy*gy);
  924. c = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)];
  925. cr = (c) & 0xff;
  926. cg = (c >> 8) & 0xff;
  927. cb = (c >> 16) & 0xff;
  928. ca = (c >> 24) & 0xff;
  929. a = nsvg__div255((int)cover[0] * ca);
  930. ia = 255 - a;
  931. // Premultiply
  932. r = nsvg__div255(cr * a);
  933. g = nsvg__div255(cg * a);
  934. b = nsvg__div255(cb * a);
  935. // Blend over
  936. r += nsvg__div255(ia * (int)dst[0]);
  937. g += nsvg__div255(ia * (int)dst[1]);
  938. b += nsvg__div255(ia * (int)dst[2]);
  939. a += nsvg__div255(ia * (int)dst[3]);
  940. dst[0] = (unsigned char)r;
  941. dst[1] = (unsigned char)g;
  942. dst[2] = (unsigned char)b;
  943. dst[3] = (unsigned char)a;
  944. cover++;
  945. dst += 4;
  946. fx += dx;
  947. }
  948. }
  949. }
  950. static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, float scale, NSVGcachedPaint* cache, char fillRule)
  951. {
  952. NSVGactiveEdge *active = NULL;
  953. int y, s;
  954. int e = 0;
  955. int maxWeight = (255 / NSVG__SUBSAMPLES); // weight per vertical scanline
  956. int xmin, xmax;
  957. for (y = 0; y < r->height; y++) {
  958. memset(r->scanline, 0, r->width);
  959. xmin = r->width;
  960. xmax = 0;
  961. for (s = 0; s < NSVG__SUBSAMPLES; ++s) {
  962. // find center of pixel for this scanline
  963. float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f;
  964. NSVGactiveEdge **step = &active;
  965. // update all active edges;
  966. // remove all active edges that terminate before the center of this scanline
  967. while (*step) {
  968. NSVGactiveEdge *z = *step;
  969. if (z->ey <= scany) {
  970. *step = z->next; // delete from list
  971. // NSVG__assert(z->valid);
  972. nsvg__freeActive(r, z);
  973. } else {
  974. z->x += z->dx; // advance to position for current scanline
  975. step = &((*step)->next); // advance through list
  976. }
  977. }
  978. // resort the list if needed
  979. for (;;) {
  980. int changed = 0;
  981. step = &active;
  982. while (*step && (*step)->next) {
  983. if ((*step)->x > (*step)->next->x) {
  984. NSVGactiveEdge* t = *step;
  985. NSVGactiveEdge* q = t->next;
  986. t->next = q->next;
  987. q->next = t;
  988. *step = q;
  989. changed = 1;
  990. }
  991. step = &(*step)->next;
  992. }
  993. if (!changed) break;
  994. }
  995. // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
  996. while (e < r->nedges && r->edges[e].y0 <= scany) {
  997. if (r->edges[e].y1 > scany) {
  998. NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany);
  999. if (z == NULL) break;
  1000. // find insertion point
  1001. if (active == NULL) {
  1002. active = z;
  1003. } else if (z->x < active->x) {
  1004. // insert at front
  1005. z->next = active;
  1006. active = z;
  1007. } else {
  1008. // find thing to insert AFTER
  1009. NSVGactiveEdge* p = active;
  1010. while (p->next && p->next->x < z->x)
  1011. p = p->next;
  1012. // at this point, p->next->x is NOT < z->x
  1013. z->next = p->next;
  1014. p->next = z;
  1015. }
  1016. }
  1017. e++;
  1018. }
  1019. // now process all active edges in non-zero fashion
  1020. if (active != NULL)
  1021. nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule);
  1022. }
  1023. // Blit
  1024. if (xmin < 0) xmin = 0;
  1025. if (xmax > r->width-1) xmax = r->width-1;
  1026. if (xmin <= xmax) {
  1027. nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scale, cache);
  1028. }
  1029. }
  1030. }
  1031. static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride)
  1032. {
  1033. int x,y;
  1034. // Unpremultiply
  1035. for (y = 0; y < h; y++) {
  1036. unsigned char *row = &image[y*stride];
  1037. for (x = 0; x < w; x++) {
  1038. int r = row[0], g = row[1], b = row[2], a = row[3];
  1039. if (a != 0) {
  1040. row[0] = (unsigned char)(r*255/a);
  1041. row[1] = (unsigned char)(g*255/a);
  1042. row[2] = (unsigned char)(b*255/a);
  1043. }
  1044. row += 4;
  1045. }
  1046. }
  1047. // Defringe
  1048. for (y = 0; y < h; y++) {
  1049. unsigned char *row = &image[y*stride];
  1050. for (x = 0; x < w; x++) {
  1051. int r = 0, g = 0, b = 0, a = row[3], n = 0;
  1052. if (a == 0) {
  1053. if (x-1 > 0 && row[-1] != 0) {
  1054. r += row[-4];
  1055. g += row[-3];
  1056. b += row[-2];
  1057. n++;
  1058. }
  1059. if (x+1 < w && row[7] != 0) {
  1060. r += row[4];
  1061. g += row[5];
  1062. b += row[6];
  1063. n++;
  1064. }
  1065. if (y-1 > 0 && row[-stride+3] != 0) {
  1066. r += row[-stride];
  1067. g += row[-stride+1];
  1068. b += row[-stride+2];
  1069. n++;
  1070. }
  1071. if (y+1 < h && row[stride+3] != 0) {
  1072. r += row[stride];
  1073. g += row[stride+1];
  1074. b += row[stride+2];
  1075. n++;
  1076. }
  1077. if (n > 0) {
  1078. row[0] = (unsigned char)(r/n);
  1079. row[1] = (unsigned char)(g/n);
  1080. row[2] = (unsigned char)(b/n);
  1081. }
  1082. }
  1083. row += 4;
  1084. }
  1085. }
  1086. }
  1087. static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity)
  1088. {
  1089. int i, j;
  1090. NSVGgradient* grad;
  1091. cache->type = paint->type;
  1092. if (paint->type == NSVG_PAINT_COLOR) {
  1093. cache->colors[0] = nsvg__applyOpacity(paint->color, opacity);
  1094. return;
  1095. }
  1096. grad = paint->gradient;
  1097. cache->spread = grad->spread;
  1098. memcpy(cache->xform, grad->xform, sizeof(float)*6);
  1099. if (grad->nstops == 0) {
  1100. for (i = 0; i < 256; i++)
  1101. cache->colors[i] = 0;
  1102. } else if (grad->nstops == 1) {
  1103. unsigned int color = nsvg__applyOpacity(grad->stops[0].color, opacity);
  1104. for (i = 0; i < 256; i++)
  1105. cache->colors[i] = color;
  1106. } else {
  1107. unsigned int ca, cb = 0;
  1108. float ua, ub, du, u;
  1109. int ia, ib, count;
  1110. ca = nsvg__applyOpacity(grad->stops[0].color, opacity);
  1111. ua = nsvg__clampf(grad->stops[0].offset, 0, 1);
  1112. ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1);
  1113. ia = (int)(ua * 255.0f);
  1114. ib = (int)(ub * 255.0f);
  1115. for (i = 0; i < ia; i++) {
  1116. cache->colors[i] = ca;
  1117. }
  1118. for (i = 0; i < grad->nstops-1; i++) {
  1119. ca = nsvg__applyOpacity(grad->stops[i].color, opacity);
  1120. cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity);
  1121. ua = nsvg__clampf(grad->stops[i].offset, 0, 1);
  1122. ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1);
  1123. ia = (int)(ua * 255.0f);
  1124. ib = (int)(ub * 255.0f);
  1125. count = ib - ia;
  1126. if (count <= 0) continue;
  1127. u = 0;
  1128. du = 1.0f / (float)count;
  1129. for (j = 0; j < count; j++) {
  1130. cache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u);
  1131. u += du;
  1132. }
  1133. }
  1134. for (i = ib; i < 256; i++)
  1135. cache->colors[i] = cb;
  1136. }
  1137. }
  1138. /*
  1139. static void dumpEdges(NSVGrasterizer* r, const char* name)
  1140. {
  1141. float xmin = 0, xmax = 0, ymin = 0, ymax = 0;
  1142. NSVGedge *e = NULL;
  1143. int i;
  1144. if (r->nedges == 0) return;
  1145. FILE* fp = fopen(name, "w");
  1146. if (fp == NULL) return;
  1147. xmin = xmax = r->edges[0].x0;
  1148. ymin = ymax = r->edges[0].y0;
  1149. for (i = 0; i < r->nedges; i++) {
  1150. e = &r->edges[i];
  1151. xmin = nsvg__minf(xmin, e->x0);
  1152. xmin = nsvg__minf(xmin, e->x1);
  1153. xmax = nsvg__maxf(xmax, e->x0);
  1154. xmax = nsvg__maxf(xmax, e->x1);
  1155. ymin = nsvg__minf(ymin, e->y0);
  1156. ymin = nsvg__minf(ymin, e->y1);
  1157. ymax = nsvg__maxf(ymax, e->y0);
  1158. ymax = nsvg__maxf(ymax, e->y1);
  1159. }
  1160. fprintf(fp, "<svg viewBox=\"%f %f %f %f\" xmlns=\"http://www.w3.org/2000/svg\">", xmin, ymin, (xmax - xmin), (ymax - ymin));
  1161. for (i = 0; i < r->nedges; i++) {
  1162. e = &r->edges[i];
  1163. fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#000;\" />", e->x0,e->y0, e->x1,e->y1);
  1164. }
  1165. for (i = 0; i < r->npoints; i++) {
  1166. if (i+1 < r->npoints)
  1167. fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#f00;\" />", r->points[i].x, r->points[i].y, r->points[i+1].x, r->points[i+1].y);
  1168. fprintf(fp ,"<circle cx=\"%f\" cy=\"%f\" r=\"1\" style=\"fill:%s;\" />", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : "#0f0");
  1169. }
  1170. fprintf(fp, "</svg>");
  1171. fclose(fp);
  1172. }
  1173. */
  1174. void nsvgRasterize(NSVGrasterizer* r,
  1175. NSVGimage* image, float tx, float ty, float scale,
  1176. unsigned char* dst, int w, int h, int stride)
  1177. {
  1178. NSVGshape *shape = NULL;
  1179. NSVGedge *e = NULL;
  1180. NSVGcachedPaint cache;
  1181. int i;
  1182. r->bitmap = dst;
  1183. r->width = w;
  1184. r->height = h;
  1185. r->stride = stride;
  1186. if (w > r->cscanline) {
  1187. r->cscanline = w;
  1188. r->scanline = (unsigned char*)realloc(r->scanline, w);
  1189. if (r->scanline == NULL) return;
  1190. }
  1191. for (i = 0; i < h; i++)
  1192. memset(&dst[i*stride], 0, w*4);
  1193. for (shape = image->shapes; shape != NULL; shape = shape->next) {
  1194. if (!(shape->flags & NSVG_FLAGS_VISIBLE))
  1195. continue;
  1196. if (shape->fill.type != NSVG_PAINT_NONE) {
  1197. nsvg__resetPool(r);
  1198. r->freelist = NULL;
  1199. r->nedges = 0;
  1200. nsvg__flattenShape(r, shape, scale);
  1201. // Scale and translate edges
  1202. for (i = 0; i < r->nedges; i++) {
  1203. e = &r->edges[i];
  1204. e->x0 = tx + e->x0;
  1205. e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
  1206. e->x1 = tx + e->x1;
  1207. e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
  1208. }
  1209. // Rasterize edges
  1210. if (r->nedges != 0)
  1211. qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
  1212. // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
  1213. nsvg__initPaint(&cache, &shape->fill, shape->opacity);
  1214. nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, shape->fillRule);
  1215. }
  1216. if (shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) {
  1217. nsvg__resetPool(r);
  1218. r->freelist = NULL;
  1219. r->nedges = 0;
  1220. nsvg__flattenShapeStroke(r, shape, scale);
  1221. // dumpEdges(r, "edge.svg");
  1222. // Scale and translate edges
  1223. for (i = 0; i < r->nedges; i++) {
  1224. e = &r->edges[i];
  1225. e->x0 = tx + e->x0;
  1226. e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
  1227. e->x1 = tx + e->x1;
  1228. e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
  1229. }
  1230. // Rasterize edges
  1231. if (r->nedges != 0)
  1232. qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
  1233. // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
  1234. nsvg__initPaint(&cache, &shape->stroke, shape->opacity);
  1235. nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, NSVG_FILLRULE_NONZERO);
  1236. }
  1237. }
  1238. nsvg__unpremultiplyAlpha(dst, w, h, stride);
  1239. r->bitmap = NULL;
  1240. r->width = 0;
  1241. r->height = 0;
  1242. r->stride = 0;
  1243. }
  1244. #endif // NANOSVGRAST_IMPLEMENTATION
  1245. #endif // NANOSVGRAST_H